一、前言

小生不才,学习安卓socke通信打了很多滚,遇到过很多问题,也翻过前辈们关于socket的讲解,很杂各有见解,案例也不是很完整,于是特地将此安卓Socket与pc端c#服务器的通信代码讲解与socket的资料整理一遍加深理解,希望能有所帮助,小生没写过几次博客,欢迎各位大佬提出宝贵意见。安卓客户端项目源代码与pc端C#服务器与客户端的资源已经上传:安卓Socket与pc端c#服务器的通信完整代码(包含C#服务器与安卓项目工程)-CSDN下载  https://download.csdn.net/download/zengpengqing1204/10374110

二、Socket的基本概念

1、套接字(socket)概念

Socket(套接字)用于描述IP地址和端口,是通信链的句柄,应用程序可以通过Socket向网络发出请求或者应答网络请求。

Socket是支持TCP/IP协议的网络通信的基本操作单元,是对网络通信过程中端点的抽象表示,包含了进行网络通信所必需的5种信息:连接所使用的协议、本地主机的IP地址、本地进程的协议端口、远地主机的IP地址以及远地进程的协议端口。

套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。

应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应 用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

2 、建立socket连接

建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。

套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发 给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

ps:其他一些几次握手的事情我就不弄出来了,没什么太大的营养,自己了解即可,重在实战

三、Socket的使用

1、socket的构造方法

Java在包java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的Socket客户端和服务器端。

  Socket的构造方法如下:

  (1)Socket(InetAddress address, int port);

  (2)Socket(InetAddress address, int port, boolean stream);

  (3)Socket(String host, int port);

  (4)Socket(String host, int port, boolean stream);

  (5)Socket(SocketImpl impl);

  (6)Socket(String host, int port, InetAddress localAddr, int localPort);

  (7)Socket(InetAddress address, int port, InetAddrss localAddr, int localPort);

  ServerSocket的构造方法如下:

  (1)ServerSocket(int port);

  (2)ServerSocket(int port, int backlog);

  (3)ServerSocket(int port, int backlog, InetAddress bindAddr);

  其中,参数address、host和port分别是双向连接中另一方的IP地址、主机名和端口号;参数stream表示Socket是流Socket还是数据报Socket;参数localAddr和localPort表示本地主机的IP地址和端口号;SocketImpl是Socket的父类,既可以用来创建ServerSocket,也可以用来创建Socket。

2、输入流和输出流

  Socket提供了方法getInputStream()和getOutPutStream()来获得对应的输入流和输出流,以便对Socket进行读写操作,这两个方法的返回值分别是InputStream和OutPutStream对象。

  为了便于读写数据,我们可以在返回的输入输出流对象上建立过滤流,如PrintStream、InputStreamReader和OutputStreamWriter等。

3、关闭Socket

  可以通过调用Socket的close()方法来关闭Socket。在关闭Socket之前,应该先关闭与Socket有关的所有输入输出流,然后再关闭Socket。

四、安卓与PC端的socket通讯

1.主程序代码附首页链接

package com.example.android_socket_pc_zpq3;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.UnknownHostException;import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;public class MainActivity extends Activity {private EditText ipEditText,portEditText,sendEditText;//声明输入IP编辑框,端口号编辑框,发送信息编辑框private TextView chatTextView;//声明聊天记录显示文本private Thread connectThread;//声明连接服务器线程private Handler messageHandler;//声明信息处理机制函数Socket socket;//声明socket对象BufferedReader bufferedReader;//声明输入流对象OutputStream outputStream;//声明输出流对象Boolean isconnectBoolean = false;//初始化socket连接值为未连接@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);init();//初始化控件}//连接服务器线程:连接服务器并接收数据      本人觉得可以放一起写Runnable connectRunnable = new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubtry {//新建socket对象,填入编辑框IP,端口号socket=new Socket(ipEditText.getText().toString(),Integer.valueOf(portEditText.getText().toString()));//取得输入流、输出流bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));outputStream=socket.getOutputStream();//接收数据可用子线程也可直接在此线程操作char[] buffer=new char[256];//定义数组接收输入流数据String bufferString="";//定义一个字符接收数组数据int conut =0;//初始化buffer数组长度为0int tag=0;//初识写入数组的位置//死循环重复接收输入流数据并进行处理while (true) {//当输入流写入buffer数组的长度大于0时   即 接收到数据时while ((conut=bufferedReader.read(buffer))>0) {//将buffer数组的数据全部写入bufferString字符类型while ( tag<buffer.length) {bufferString=bufferString+buffer[tag];tag++;}//将数据给messageHandler刷新UI界面Message msgMessage =new Message();msgMessage.obj=bufferString;msgMessage.what=1;messageHandler.sendMessage(msgMessage);//初始化数据,以便处理下一条输入流信息tag=0;bufferString="";}}} catch (NumberFormatException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}};//初始化所有控件private void init() {ipEditText=(EditText) findViewById(R.id.IpeditText);portEditText=(EditText)findViewById(R.id.PorteditText);sendEditText=(EditText)findViewById(R.id.sendeditText);chatTextView=(TextView)findViewById(R.id.chattextView);//连接服务器按钮事件findViewById(R.id.connectbutton).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {//逻辑判断socket是否连接上,再做操作if (isconnectBoolean==false) {connectThread=new Thread(connectRunnable);connectThread.start();Toast.makeText(MainActivity.this, "连接服务器成功", 2).show();isconnectBoolean=true;}}});//断开服务器按钮事件findViewById(R.id.breakbutton).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {//逻辑判断socket是否连接上,再做操作if (isconnectBoolean==true) {if (socket !=null) {try {//先关闭socket连接,再关闭输入流、输出流,socket.close();socket = null;bufferedReader.close();outputStream.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}//中断连接线程connectThread.interrupt();Toast.makeText(MainActivity.this, "断开连接!", 2).show();isconnectBoolean=false;}}});//发送信息给服务器按钮事件findViewById(R.id.sendbutton).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {//这里可以用线程也可以不用线程try {//输出流写入发送编辑框的信息并指定类型UTF-8,注意要加换行outputStream.write((sendEditText.getText().toString()+"\n").getBytes("utf-8"));//输出流发送至服务器outputStream.flush();//handlerMessage处理发送信息刷新UI界面Message msgMessage =new Message();msgMessage.obj=sendEditText.getText().toString();msgMessage.what=0;messageHandler.sendMessage(msgMessage);} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}});//处理接收服务器信息以及发送至服务器信息呈现聊天室效果messageHandler = new Handler(){public void handleMessage(android.os.Message msgMessage) {String sendString="";String receiveString="";switch (msgMessage.what) {case 0:sendString="曾鹏晴说:"+msgMessage.obj.toString()+"\n";chatTextView.append(sendString);break;case 1:receiveString="小权权说:"+msgMessage.obj.toString()+"\n";chatTextView.append(receiveString);break;default:break;}}};}}

2、布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity" ><EditTextandroid:id="@+id/IpeditText"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_alignParentTop="true"android:layout_marginLeft="36dp"android:ems="7"android:text="192.168.1.101" ><requestFocus /></EditText><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBaseline="@+id/IpeditText"android:layout_alignBottom="@+id/IpeditText"android:layout_alignParentLeft="true"android:text="IP:" /><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBaseline="@+id/IpeditText"android:layout_alignBottom="@+id/IpeditText"android:layout_toRightOf="@+id/IpeditText"android:text="Port:" /><EditTextandroid:id="@+id/PorteditText"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBaseline="@+id/textView2"android:layout_alignBottom="@+id/textView2"android:layout_alignParentRight="true"android:ems="4"android:text="8488" /><Buttonandroid:id="@+id/connectbutton"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/textView1"android:layout_below="@+id/IpeditText"android:layout_marginTop="14dp"android:text="连接服务器" /><Buttonandroid:id="@+id/breakbutton"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBaseline="@+id/connectbutton"android:layout_alignBottom="@+id/connectbutton"android:layout_marginLeft="41dp"android:layout_toRightOf="@+id/connectbutton"android:text="断开服务器" /><EditTextandroid:id="@+id/sendeditText"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignRight="@+id/PorteditText"android:layout_below="@+id/connectbutton"android:layout_marginTop="16dp"android:ems="10"android:text="hello 小权权" /><Buttonandroid:id="@+id/sendbutton"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/sendeditText"android:layout_alignRight="@+id/sendeditText"android:layout_below="@+id/sendeditText"android:layout_marginTop="14dp"android:text="发送信息至服务器" /><TextViewandroid:id="@+id/textView3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/sendbutton"android:layout_below="@+id/sendbutton"android:layout_marginTop="14dp"android:text="聊天记录:" /><TextViewandroid:id="@+id/chattextView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/textView3"android:layout_toRightOf="@+id/textView1"android:text="" /></RelativeLayout>

3、PC端c#服务器代码附首页链接

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;using System.Net.Sockets;
using System.Net;
using System.Threading;namespace socket
{/// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}Socket ServerSocket = null;private void btnStart_Click(object sender, RoutedEventArgs e){IPEndPoint IPE = new IPEndPoint(IPAddress.Parse(tboxIP.Text), Int32.Parse(tboxPort.Text));ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);ServerSocket.Bind(IPE);ServerSocket.Listen(10);showmsg("服务器已启动,监听中...");Thread thread = new Thread(ListenClientConnect);thread.IsBackground=true;thread.Start();}Dictionary<string, Socket> dic = new Dictionary<string, Socket>();private void ListenClientConnect(object obj){while (true){Socket socketClient = ServerSocket.Accept() ;string RemoteIP = socketClient.RemoteEndPoint.ToString();dic.Add(RemoteIP, socketClient);Dispatcher.Invoke(()=>lstboxIP.Items.Add(RemoteIP));showmsg(RemoteIP + "已连接");Thread recieveThread = new Thread(recievemsg);recieveThread.IsBackground = true;recieveThread.Start(socketClient);}}private void recievemsg(object soc){Socket socketClient = (Socket)soc;while (true){byte[] buffer = new byte[1024];int n = socketClient.Receive(buffer);//string msg = Encoding.Default.GetString(buffer, 0, n);string msg = Encoding.UTF8.GetString(buffer, 0, n);//可在这里指定接受数据格式showmsg(socketClient.RemoteEndPoint.ToString()+":"+msg);}}private void showmsg(string p){Dispatcher.BeginInvoke(new Action(() =>{rtbx.AppendText(p + "\r\n");}));}private void btnStop_Click(object sender, RoutedEventArgs e){ServerSocket.Close();}private void btnSend_Click(object sender, RoutedEventArgs e){showmsg(tboxMsg.Text);string ip = lstboxIP.SelectedValue.ToString();//byte[] by = Encoding.UTF8.GetBytes(tboxMsg.Text);byte[] by = Encoding.Default.GetBytes(tboxMsg.Text);dic[ip].Send(by,0);tboxMsg.Text = "";}}
}

4、布局文件

<Window x:Class="socket.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow" Height="350" Width="525"><Grid><Label x:Name="label" Content="IP地址:" HorizontalAlignment="Left" Margin="24,15,0,0" VerticalAlignment="Top"/><TextBox x:Name="tboxIP" HorizontalAlignment="Left" Height="23" Margin="86,17,0,0" TextWrapping="Wrap" Text="192.168.1.101" VerticalAlignment="Top" Width="92"/><Label x:Name="label1" Content="端口:" HorizontalAlignment="Left" Margin="183,16,0,0" VerticalAlignment="Top"/><TextBox x:Name="tboxPort" HorizontalAlignment="Left" Height="23" Margin="228,17,0,0" TextWrapping="Wrap" Text="8488" VerticalAlignment="Top" Width="43"/><Button x:Name="btnStart" Content="服务器启动" HorizontalAlignment="Left" Margin="287,19,0,0" VerticalAlignment="Top" Width="75" Click="btnStart_Click"/><Button x:Name="btnStop" Content="服务器停止" HorizontalAlignment="Left" Margin="377,19,0,0" VerticalAlignment="Top" Width="75" Click="btnStop_Click"/><ListBox x:Name="lstboxIP" HorizontalAlignment="Left" Height="180" Margin="377,65,0,0" VerticalAlignment="Top" Width="116"/><Button x:Name="btnSend" Content="发送信息" HorizontalAlignment="Left" Margin="377,271,0,0" VerticalAlignment="Top" Width="75" Click="btnSend_Click"/><TextBox x:Name="tboxMsg" HorizontalAlignment="Left" Height="23" Margin="24,270,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="320"/><RichTextBox x:Name="rtbx" HorizontalAlignment="Left" Height="180" Margin="24,65,0,0" VerticalAlignment="Top" Width="320"><FlowDocument><Paragraph></Paragraph></FlowDocument></RichTextBox></Grid>
</Window>

5、聊天室效果图

原文地址:https://blog.csdn.net/Zengpengqing1204/article/details/80083651

安卓Socket与pc端c#服务器的通信 附完整代码相关推荐

  1. Java网络编程 Socket、ServerSocket 详解,方法介绍及完整代码示例

    Java网络编程 Socket.ServerSocket 详解,方法介绍及完整代码示例 概念 什么是网络编程? 网络编程是指编写运行在多个设备(计算机)的程序,这些设备通过网络连接起来.当这些通过网络 ...

  2. SpringBoot(23) 集成socket.io服务端和客户端实现通信

    一.前言 websocket和socket.io区别? websocket 一种让客户端和服务器之间能进行双向实时通信的技术 使用时,虽然主流浏览器都已经支持,但仍然可能有不兼容的情况 适合用于cli ...

  3. Socket实现Android客户端与服务器的通信

    前言:题目要求故写一下总结. 1.什么是Socket? 网络用语叫套接字原理是基于tcp/ip 协议的一种通信手段,目前题目中要求无非就是当客户端数据异常时推送给服务器报警信息 往常接下来都是先看效果 ...

  4. vue移动端和pc端切换显示两套不同的代码

    首先在App.vue中 <template ><div id="app" ><!-- <router-view />--><r ...

  5. 基于卷积神经网络的数字手势识别APP(安卓) 毕业设计 附完整代码

    项目简介 这是一个基于卷积神经网络的数字手势识别 APP(安卓),主要功能为:通过手机摄像头识别做出的数字手势,能够识别数字 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 对应的手 ...

  6. Reactor实现http服务器,附完整代码

    如何在reactor的基础上实现业务?就是怎么利用reactor做服务器,并实现服务器的业务. 本文基于reactor,实现简单的http协议封装.只是为了说明reactor如何做业务,真正的http ...

  7. 我的世界linux联机游戏,MineCraft 我的世界 – PC 端联机服务器搭建 ( Linux )

    1.安装 Screen 任务时间:时间未知 MineCraft 是长期运行的,但是 Linux 下只要关闭连接,所有运行在该窗口下的服务都是被 kill,所以我们需要 Screen 来保持我们的 Mi ...

  8. 天刀手游pc端显示服务器维护,天刀手游电脑版无法更新网络修复工具

    天涯明月刀手游电脑版更新失败修复工具是一款可以解决天涯明月刀手游电脑版更新失败问题的工具,最近很多玩家反映自己的游戏更新后无法打开,大家可以利用这款天涯明月刀手游电脑版更新失败修复工具修复网络来解决这 ...

  9. socket.io服务端是java_SpringBoot(23) 集成socket.io服务端和客户端实现通信

    @Slf4j @Service(value = "socketIOService") public class SocketIOServiceImpl implements ISo ...

最新文章

  1. Apache服务器下使用 ab 命令进行压力测试
  2. linux shell 字符串操作(长度,查找,替换)详解
  3. linux设备驱动第一篇:设备驱动程序简介
  4. 基于verilog按键消抖设计
  5. C#--WinForm项目主窗体设计
  6. vb6.0服务器组件安装失败,win10安装vb6.0总是失败怎么办?win10 vb6.0安装不了的解决办法...
  7. 企业数字化转型与中台建设全攻略:什么阶段进行?有哪些方法?
  8. 【LeetCode】Merge Two Sorted Lists(合并两个有序链表)
  9. android 调用wcf json,使用 JSONP
  10. 北航计算机组成原理课程设计-2020秋 PreProject-Logisim-Logisim仿真与调试应用与挑战
  11. 网络工程初学者的学习方法及成长之路(红茶三杯)
  12. 群贤路附近哪有计算机学校,袍江,镜湖,皋埠,富盛…绍兴各镇学校2017年施教区划定!你家孩子该在哪就读?...
  13. 开发板与思岚RPLIDAR A系列雷达通过串口获取数据
  14. Windows使用ROS机器人操作系统12记录
  15. Java线程等待唤醒机制(加深理解)
  16. Git生成公钥、私钥以及ssh key配置
  17. 有道词典工具(命令行+GUI)
  18. KaTex的一个简单例子
  19. 分布式存储系统 之 数据备份
  20. java毕业设计社区流浪猫狗救助网站源码+lw文档+mybatis+系统+mysql数据库+调试

热门文章

  1. Java实现信用卡校验
  2. Bingo NFT 如何帮助交易者和投资者分析市场
  3. 在线协作文档综合评测 :金山文档、腾讯文档、石墨文档
  4. 搜索引擎的爬虫技术研究
  5. qca4004 linux wifi,物联网 WIFI 一键配置原理(smartconfig) ESP8266/QCA4004
  6. CentOS解决nginx autoindex 截断文件名,末尾出现乱码
  7. 设计如下类: 1) 建立一个Point类,表示平面中的一个点;建立一个Line类,表示平面中的一条线端, 内含两个Point类的对象;建立Triangle类,表示一个三角形
  8. 脚本编写一个10秒的倒计时和1分10秒的倒计时
  9. 反向放大器为何要使用同相增益(也称作噪声增益),来计算带宽
  10. 导致联想拯救者y7000触控板失灵的一种可能