你也可以写个聊天程序

时间:2022-04-30 22:01:49

我们做软件工作的虽然每天都离不开网络,可网络协议细节却不是每个人都会接触和深入了解。我今天就来和大家一起学习下Socket,并写一个简单的聊天程序。

一些基础类

首先我们每天打开浏览器访问网页信息都是使用的HTTP/HTTPS协议,而HTTP是通过的TCP建立的连接。TCP底层又是通过的Socket套接字进行的通信。所以他们之间的抽象关系是:

你也可以写个聊天程序

我们在学习Socket编程的时候可能会需要用到IPEndPoint、Dns、IPAddress等类,再往上TCP相关有TcpListener、TcpClient、NetworkStream,再往上就是大家熟悉的HttpClient等。
IPEndPoint、Dns、IPAddress基础作用如下:

//根据DNS获取域名绑定的IP foreach (var address in Dns.GetHostEntry("www.baidu.com").AddressList) { Console.WriteLine($"百度IP:{address}"); } //字符串转IP地址 IPAddress ipAddress = IPAddress.Parse("192.168.1.101"); //通过IP和端口构造IPEndPoint对象,用于远程连接 //通过IP可以确定一台电脑,通过端口可以确定电脑上的一个程序 IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 80); 利用Socket编写聊天程序

我们首先从Socket开始讲起。
要实现Socket通信,先得有个服务端的监听,再有个客户端的连接,然后客户端和服务端就可以通信了。如下:

你也可以写个聊天程序


服务端代码如下: //1 创建Socket对象 socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //2 绑定ip和端口 IPAddress ip = IPAddress.Parse("127.0.0.1"); IPEndPoint ipEndPoint = new IPEndPoint(ip, 50001); socketServer.Bind(ipEndPoint); //3、开启侦听(等待客户机发出的连接),并设置最大客户端连接数为10 socketServer.Listen(10); //4、【阻塞】,等待客户端连接 Socket newSocket = socketServer.Accept(); //5、【阻塞】,等待读取客户端发送过来的数据 byte[] data = new byte[1024 * 1024]; int readLeng = newSocket.Receive(data, 0, data.Length, SocketFlags.None); //6、读取数据 var msg = Encoding.UTF8.GetString(data, 0, readLeng);

客户端代码如下:

//1 创建Socket对象 socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //2 连接到服务端 IPAddress ip = IPAddress.Parse("127.0.0.1"); IPEndPoint ipEndPoint = new IPEndPoint(ip, 50001); socketClient.Connect(ipEndPoint); //3 发送消息到服务端 socketClient.Send(Encoding.UTF8.GetBytes("你好,农码一生"));

到此,我们就可以开启服务端的服务,并接受客户端的发来的消息了。
不过,这里有个很大的问题,服务端只能建立一个客户端连接和接受一次客户端发来的消息。如果想要连接更多的客户端和接受无数次的消息,服务端代码两处阻塞的地方需要另外开一个线程然后包到循环里面去。
修改后的服务端代码如下:

void .... () { //1 创建Socket对象 socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //2 绑定ip和端口 IPAddress ip = IPAddress.Parse("127.0.0.1"); IPEndPoint ipEndPoint = new IPEndPoint(ip, 50001); socketServer.Bind(ipEndPoint); //3、开启侦听(等待客户机发出的连接),并设置最大客户端连接数为10 socketServer.Listen(10); //开启新的线程,循环等待新的客户端连接 Task.Run(() => { Accept(socketServer); }); } void Accept(Socket socket) { while (true) { //4、【阻塞】,等待客户端连接 Socket newSocket = socket.Accept(); //开启新的线程,循环等待接收新的数据 Task.Run(() => { Receive(newSocket); }); } } void Receive(Socket newSocket) { while (true) { //5、【阻塞】,等待读取客户端发送过来的数据 byte[] data = new byte[1024 * 1024]; int readLeng = newSocket.Receive(data, 0, data.Length, SocketFlags.None); //6、读取数据 var msg = Encoding.UTF8.GetString(data, 0, readLeng); } }