SOCKET(套件字)是支持TCP/IP 网络通信的基本操作单元。System.Net.Sockets 命名空间提供了TcpClient类、TcpListener类和UdpClient类。这些类封装了不同传输协议建立连接、操作方法的细节。 套接字有3中不同的类型: 流套接字:面向连接的TCP通信。 数据报套接字:实现无连接的UDP通信。 原始套接字:实现IP数据报通信。 socket类的构造函数: public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType); 对应参数的意义: AddressFamily:网络类型,如IP版本4、IP版本6等; SocketType :套间字类型,如流套接字,数据报套接字等; ProtocolType :传输协议类型,如TCP、UDP等。
在面向连接的套接字中,使用TCP来建立两个IP地址端点之间的会话。一旦设备建立的连接,就可以在设备之间进行可靠的数据传输。
为了建立面向连接的套接字,服务器和客户端需要分别进行编程。
连接过程需要3个过程:服务器监听、客户端请求、连接确认。
(1)服务器编程。 在服务器中,首先创建一个本地套接字对象。如下: //使用IPv4地址,流式socket方式,tcp协议传递数据
Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);然后,将套接字绑定到本地IP和端口上。Bind方法用于完成绑定工作。如下:
//ip地址 IPAddress ip = IPAddress.Parse(txtIP.Text); // IPAddress ip = IPAddress.Any; //端口号 IPEndPoint point=new IPEndPoint(ip,int.Parse(txtPort.Text)); socket.Bind(point);将套接字与端口绑定之后,就用Listen方法等待客户端发出的尝试连接。如下:
socket.Listen(10);Listen方法,自动将客户连接请求放到请求队列中,参数指出系统等待用户程序服务排队的连接数,超过连接数的任何客户都不能与服务器进行通信。
在Listen方法执行之后,服务器已经做好了接收任何连接的准备。这时,可用Accept方法从请求队列中获取连接。如下: socket.Accept();
程序执行到Accept方法时会阻塞,直到收到客户端的连接请求,才继续执行下一条语句。服务器一旦接受了该客户端的连接请求,Accept方法立即返回一个与该客户端通信的信的套接字,该套接字中既包含了本机的IP地址和端口号,也包含了客户端的IP地址和端口号,然后利用此套接字与客户端进行通信了。
在实际应用场合中,为了能够与多个客户端通信,可以用一个线程监听客户端的连接请求,在该线程中循环调用Accept方法接收新的客户端连接。如下:
Thread th = new Thread(Listen); th.IsBackground = true; th.Start(socketWatch); Socket socketSend; Dictionary<string, Socket> diclist = new Dictionary<string, Socket>(); /// <summary> /// 等待客户端的连接,并且创建与之通信用的Socket /// </summary> /// <param name="obj"></param> private void Listen(object obj) { Socket socketWatch = obj as Socket; while (true) { try { //等待客户端的连接,并且创建一个用于通信的Socket socketSend = socketWatch.Accept(); //将客户端socket存到集合中 diclist.Add(socketSend.RemoteEndPoint.ToString(), socketSend); //将客户端ip 存到下拉列表中 comboBox1.Items.Add(socketSend.RemoteEndPoint.ToString()); ShowBox(socketSend.RemoteEndPoint.ToString() + ":连接成功"); // Thread th = new Thread(Receive); th.IsBackground = true; th.Start(socketSend); } catch { } } }(2)客户端编程。 客户端利用Socket的connect方法向远程主机的断点发起连接请求。并将自身绑定到系统自动分配的端电上。如下:
IPAddress ip = IPAddress.Parse("192.168.10.3"); IPEndPoint point = new IPEndPoint(ip, int.Parse("9008")); localSocket= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); localSocket.Connect(point);程序运行后,客户端与服务器建立连接之前,系统不会执行connect语句下面的内容,而是处于阻塞状态,知道连接成功或出现异常为止。
客户端与服务器建立连接,客户端和服务器都可以使用Socket对象的Send和Receive方法进行通信。 (1)服务器端编程 当服务器接收客户端的连接请求成功时,Accept方法将返回包含该客户端IP地址及端口号信息的套接字。服务器可以用该套接字与客户端进行通信。 a.发送消息
Socket clientsocket = socketWatch.Accept(); //建立连接后,用Send方法向客户端发送消息 clientsocket.Send(Encoding.ASCII.GetBytes("server send Hello"));b、接收消息
//客户端连接成功后,服务器端该接受客户端发来的额消息 byte[] buffer = new byte[1024 * 1024 * 2]; //时间接收到的有效字节数 int r = socketSend.Receive(buffer); if (r == 0) { break; } string str = Encoding.UTF8.GetString(buffer, 0, r); ShowBox(socketSend.RemoteEndPoint + ":" + str); //输出打印消息(2)客户端编程。 客户端可直接使用本地套接字的Send 方法向服务器发送消息,利用Receive方法接收服务器信息,例如: a.向服务器发送消息
localSocket.Connect(point); string str = textBox4.Text.Trim(); //添加文本 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str); localSocket.Send(buffer); //发送b.接收服务器发来的消息
byte[] buffer = new byte[1024 * 1024 * 2]; localSocket.Receive(buffer); Console.WriteLine("接收服务器消息:{0}",Encoding.ASCII.GetString(buffer))注意通信完成后,必须先用Shutdown方法停止会话,然后关闭Socket实例。
localSocket.Shutdown(SocketShutdown.Both); //在套接字上既停止发送也停止接收。 localSocket.Close();参考资料:《C#网络编程第2版》马骏主编 人民邮电出版社
示例程序及代码: 客户端界面: 服务端界面 程序地址:https://download.csdn.net/download/qq_21291397/12983392