Scoket 是 .Net 常用的一种通讯方式,基于 System.Net.Sockets ,我们可以实现 Socket 通讯的基本功能
Socket 基本概念
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket
Socket 作用场景
消息的实时发送或接收(如聊天室,消息推送等)
Socket 基本流程
1:服务端监听某个端口
2:客户端向服务端地址和端口发起Socket请求
3:服务器接收连接请求后创建Socket连接,并维护这个连接队列
4:客户端和服务端就建立起了双工同信,客户端与服务端就可以实现彼此发送消息
Socket 基本方法
1.服务端-绑定本地的网络节点(Bind)
把一个地址族中的特定地址赋给socket,例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket
2.服务端-网络监听(Listen)
如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求
3.服务端-Socket请求接收(Accept)
将监听到的请求进行接收,这样一个Socket连接就建立好了
4.客户端-发起Socket请求(Connect)
通过配置服务端的IP地址,端口号等信息,进行Socket的请求
5.消息发送(Send)
实际上,Socket 的消息发送并不是直接将消息直接发送到目标主机,仅仅是把buffer中的数据copy到socket的发送缓冲区中
在适当的时机,会把socket发送缓冲区的数据发送到接收方的socket接受缓冲区
6.消息接收(Receive)
从接收方的socket接受缓冲区中把数据copy到应用程序的buffer中。如果应用程序一直没有调用Receive()读取的话,此数据会一直缓存在相应的socket的接收缓冲区
Socket 实际效果
Socket 具体实现
服务端
class Program { static Socket socket = null; public static void Main(string[] args) { ServerStart(); Console.ReadKey(); } public static void ServerStart() { //定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议) socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //服务端发送信息需要一个IP地址和端口号 IPAddress address = IPAddress.Parse("127.0.0.1"); //将IP地址和端口号绑定到网络节点point上 IPEndPoint point = new IPEndPoint(address, 8888); //监听绑定的网络节点 socket.Bind(point); //将套接字的监听队列长度限制为20 socket.Listen(int.MaxValue); Console.WriteLine($"监听{socket.LocalEndPoint.ToString()}消息开始"); //利用线程后台执行监听,否则程序会假死 Thread thread = new Thread(WatchConnecting); thread.IsBackground = true; thread.Start(); } public static void WatchConnecting() { Socket connection = null; while (true) { connection = socket.Accept(); //获取客户端的IP和端口号 IPAddress clientIP = (connection.RemoteEndPoint as IPEndPoint).Address; int clientPort = (connection.RemoteEndPoint as IPEndPoint).Port; //让客户显示"连接成功的"的信息 string sendmsg = $"连接成功,你的IP:{clientIP},端口{clientPort}"; SendData(connection, sendmsg); //客户端网络结点号 string remoteEndPoint = connection.RemoteEndPoint.ToString();//ip:port //显示与客户端连接情况 Console.WriteLine(remoteEndPoint + "客户端已连接!"); Thread thread = new Thread(RecvData); thread.IsBackground = true; thread.Start(connection); } } public static void RecvData(object obj) { Socket socket = (Socket)obj; if (socket == null || socket.Connected == false) { Console.WriteLine("socket为null,或者未连接到远程计算机"); } try { while (true) { if (socket.Available != 0)//不接收数据量为空的请求 { byte[] buffer = new byte[socket.Available];//设置缓冲区大小 int receiveNumber = socket.Receive(buffer); string data = Encoding.UTF8.GetString(buffer, 0, receiveNumber); Console.WriteLine($"来自{(socket.RemoteEndPoint as IPEndPoint).Address}:{(socket.RemoteEndPoint as IPEndPoint).Port}的消息:{data}"); } } } catch (SocketException ex) { Console.WriteLine("连接已自动断开" + ex.Message); } } public static void SendData(Socket socket, string msg) { if (socket == null || socket.Connected == false) { Console.WriteLine("参数socket为null,或者未连接到远程计算机"); } byte[] buffer = Encoding.UTF8.GetBytes(msg); if (buffer == null || buffer.Length == 0) { Console.WriteLine("参数buffer为null ,或者长度为 0"); } try { socket.Send(buffer); } catch (SocketException) { } } }
客户端
class Program { static Socket socket; static void Main(string[] args) { socket = ConnectServer("127.0.0.1", 8888); while (true) { var msg = Console.ReadLine(); SendData(socket, msg); } } public static Socket ConnectServer(string ip, int port) { try { IPAddress ipAddress = IPAddress.Parse(ip); IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port); socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socket.Connect(ipEndPoint); if (socket.Connected == false) { Console.WriteLine("连接服务端失败"); socket = null; } else { new Thread(RecvData).Start(socket); Console.WriteLine("连接服务端成功"); } } catch (Exception ex) { Console.WriteLine(ex.Message); } return socket; } public static void SendData(Socket socket, string msg) { if (socket == null || socket.Connected == false) { Console.WriteLine("参数socket为null,或者未连接到远程计算机,尝试重新连接"); socket = ConnectServer("127.0.0.1", 8888);//断线重连 } byte[] buffer = Encoding.UTF8.GetBytes(msg); if (buffer == null || buffer.Length == 0) { Console.WriteLine("参数buffer为null ,或者长度为 0"); } try { socket.Send(buffer); } catch (SocketException) { } } public static void RecvData(object obj) { Socket socket = (Socket)obj; if (socket == null || socket.Connected == false) { Console.WriteLine("socket为null,或者未连接到远程计算机,尝试重新连接"); socket = ConnectServer("127.0.0.1", 8888);//断线重连 } try { while (true) { if (socket.Available != 0)//不接收数据量为空的请求 { byte[] buffer = new byte[socket.Available]; // 已经有数据等待接收 int receiveNumber = socket.Receive(buffer); string data = Encoding.UTF8.GetString(buffer, 0, receiveNumber); Console.WriteLine($"来自{(socket.RemoteEndPoint as IPEndPoint).Address}:{(socket.RemoteEndPoint as IPEndPoint).Port}的消息:{data}"); } } } catch (SocketException ex) { Console.WriteLine("连接已自动断开" + ex.Message); } } }