1、流程图
首先看一下C#中面向连接的套接字(TCP)的编程流程:
2、服务器建立连接、收发数据、关闭连接程序段:
1)建立连接
//创建本地套接字对象,IPV4寻址方式,基于TCP的Stream Socket(流式套接字0) Socket localSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPHostEntry local = Dns.GetHostByName(Dns.GetHostName()); //HFY::获取本机主机 IPEndPoint iep = new IPEndPoint(local.AddressList[0], 8088); //HFY::获取本地主机的IP和端口号 localSocket.Bind(iep); //HFY::将套接字与本地端口绑定 localSocket.Listen(10); //HFY::启动监听 Socket clientSocket = localSocket.Accept(); //HFY::等待接受连接,返回一个与客户端通信的新的套接字
2)收发数据
clientSocket.Send(Encoding.ASCII.GetBytes("server send data")); //HFY::向客户端发送数据 //HFY::定义一1024字节的接收缓冲区,从客户端接受到的数据存如缓冲区中 byte[] buffer = new Byte[1024]; int receivedNum = clientSocket.Receive(buffer);
3)关闭连接
//HFY::shutdown函数停止回话,保证所有数据已收发完成,再关闭socket连接 localSocket.Shutdown(SocketShutdown.Both); localSocket.Close();
这个方法允许socket对象一直等待,直到将内部缓冲区的数据发送完为止。
3、客户端连接到服务器、收发数据、关闭连接:
1)连接到服务器
//HFY::指定服务器的IP和端口号,调用Connect函数向服务器发起连接,并将自身绑定到系统分配的端点上 IPAddress remoteHost = IPAddress.Parse("10.64.24.77"); IPEndPoint iep = new IPEndPoint(remoteHost,8088); Socket localSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); localSocket.Connect(iep);
2)收发数据
收发数据过程与服务器类似:
localSocket.Send(Encoding.ASCII.GetBytes("client send data")); //HFY::客户端向服务器发送数据 //HFY::定义一1024字节的接收缓冲区,从服务器接受到的数据存入缓冲区中 byte[] buffer = new Byte[1024]; int receivedNum = localSocket.Receive(buffer);
3)关闭连接
关闭连接过程与服务器相同:
localSocket.Shutdown(SocketShutdown.Both);
localSocket.Close();
4、TCP类:
为了简化网络编程,.NET对套接字进行了封装,封装了TcpListener类和TcpClient类。TcpListener类用于监听客户端的连接请求,TcpClient类用于提供本地主机和远程主机的连接信息。
5、使用TCP类编写服务器:
1)创建一个TcpListener对象,与本地IP和端口号绑定,调用start方法在指定的端口监听:
IPAddress localIP = Dns.GetHostAddresses(Dns.GetHostName())[0]; //HFY::获取本地IP TcpListener tcpListener = new TcpListener(localIP, 8088); //HFY::创建TcpListener对象 tcpListener.Start(); //HFY::开始监听
2)在单独的线程中,循环调用AcceptTcpClient方法接受客户端的连接请求,该方法返回TcpClient对象,利用返回的TcpClient对象的GetStream方法得到NetWorkStream对象。再通过NetWorkStream对象获得BinaryReader对象、BinaryWriter对象,为与客户端通讯做准备:
//HFY::创建一个线程,用于循环等待客户端的连接,AcceptClientConnect是自己定义的一个函数 Thread threadAccept = new Thread(AcceptClientConnect); threadAccept.Start(); //HFY::启动线程 //HFY::线程执行的AcceptClientConnect方法,用于接收客户端的请求 void AcceptClientConnect() { while (true) //HFY::循环接受 { try { tcpClient = tcpListener.AcceptTcpClient(); //HFY::获取TcpClient对象 if (tcpClient != null) { networkStream = tcpClient.GetStream(); //HFY::获取NetworkStream对象 } } catch { } } }
3)每得到一个新的TcpClient对象,就创建一个与该客户对应的线程,在线程中与对于那个的客户进行通信
Thread threadReceive = new Thread(ReceiveMessage); threadReceive.Start();
其中,ReceiveMessage为接受消息的函数,自行定义。
4)根据传送的情况确定是否关闭与客户端的连接,如:
if (Br != null) { Br.Close(); } if (Bw != null) { Bw.Close(); } if (tcpClient != null) { tcpClient.Close(); } //HFY::在关闭连接之前,要先关闭读、写流Br和Bw。在停止服务后,服务器可以断开监听 tcpListener.Stop();
6、使用TCP类编写客户端:
1) 创建TcpClient对象
tcpClient = new TcpClient(); //HFY::创建TcpClient对象
2)使用Connect函数连接到服务器
tcpClient.Connect("10.64.24.77",8088); //HFY::连接到指定的服务器端口
3)得到网络流
//HFY::使用tcpClient对象得到的GetStream函数得到网络流,再通过该网络流与服务器进行数据的传输 if (tcpClient != null) { networkStream = tcpClient.GetStream(); Br = new BinaryReader(networkStream); Bw = new BinaryWriter(networkStream); }
4)创建接受线程
//HFY::创建一个线程,循环接受并处理发送过来的消息 Thread threadReceive = new Thread(ReceiveMessage); threadReceive.Start();
5)关闭连接
if (Br != null) { Br.Close(); } if (Bw != null) { Bw.Close(); } if (tcpClient != null) { tcpClient.Close(); }