您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 广告经营 > 第10章TCP协议开发
1第10章TCP协议开发10.1相关概念10.2定义与获取主机信息10.3同步套接字编程10.4同步套接字开发举例——简单聊天程序10.5使用TcpClient和TcpListener简化TCP编程10.6异步套接字编程10.7异步套接字开发举例210.1基本概念•基本概念(相关概念)–同步发送方将数据包发送到网络上以后,不等接收方响应,就接着发送下一个数据包。–异步发送方将数据包发送到网络上以后,等接收方做出响应后,才接着发送下一个数据包。3-同步套接字在通过Socket进行连接、接收、发送操作时,客户机或服务器会暂停当前工作,处于等待状态,即一直等到有数据时才继续执行下面的语句。一般在阻塞方式下使用这种方式。可见,同步套接字适用于网络传输量不太大的情况。当网络传输量很大时,长时间的等待可能会让用户无法忍受。-异步套接字在通过Socket进行连接、接收、发送操作时,客户机或服务器不会暂停当前工作,而是利用callback机制进行连接、接收和发送处理。异步套接字适用于需要在网络上进行大量数据传输的应用程序,比如有几万客户同时传输的情况。410.2定义与获取主机信息•定义主机对象–IPEndPoint类–IPAddress类•获取主机信息–Dns类中常用方法•Dns.GetHostName()•Dns.GetHostByName(stringhostname)•Dns.GetHostByAddress(address)•Dns.Resolve()51.定义主机对象IPEndPoint类包含应用程序连接到主机上的服务所需的主机和端口信息。通过组合服务的主机IP地址和端口号,IPEndPoint类形成到服务的连接点。常用的方法原型:publicIPEndPoint(IPAddressaddress,intport);说明:address:IP地址port:端口号功能:初始化IPEndPoint类的实例。用法举例:IPAddressmyServerIP=newIPAddress.Parse(“127.0.0.1”);IPEndPointmyServer=newIPEndPoint(myServerIP,13);62.主机解析•程序实例——Dns.Resolve()的使用usingSystem;usingSystem.Net;publicclassTestFileStream{staticvoidMain(){Console.Write(输入主机名或者IP地址:);stringstr=Console.ReadLine();IPHostEntryhost=Dns.Resolve(str);for(inti=0;ihost.AddressList.Length;i++){Console.WriteLine(host.AddressList[i].ToString());Console.WriteLine(host.HostName);}Console.ReadLine();}}710.3同步套接字编程1.服务器端口绑定与监听在服务器与客户机连接传输数据前,服务器需要做以下事情:1)创建一个套接字。2)创建本地IPEndPoint对象。3)使用Bind()方法将所创建的套接字与本地IPEndPoint绑定。4)使用Listen()方法设置套接字为监听模式。5)使用Accept()方法接收客户端连接请求并为客户端创建一个客户端套接字。8实现方法usingSystem.Net;usingSystem.Net.Sockets;……IPAddressip=IPAddress.Parse(127.0.0.1);IPEndPointiep=newIPEndPoint(ip,6788);Socketsocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);socket.Bind(iep);socket.Listen(10);//最多允许10个客户端同时连接while(true){SocketclientSocket=socket.Accept();……}92.客户端建立与服务器的连接客户端在传送数据前,只需要做两件事:1)创建一个套接字。2)使用Socket类的Connect()方法将套接字与远程服务器地址相连。IPAddressip=IPAddress.Parse(202.196.101.246);//服务器IPIPEndPointiep=newIPEndPoint(ip,6788);Socketsocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);socket.Connect(iep);103.发送数据(1)使用Socket类的Send()方法(2)使用NetworkStream类的Write()方法。注意:不论是使用Send()方法或者使用Write()方法,都必须先将发送的数据转换为字节数组,然后使用Send()或Write()将数据发送出去。实际上,这个字节数组的数据并不是直接发送到远程机器上,而是发送到了TCP缓冲区中(该缓冲区默认大小为1024字节)。11(1)使用Socket类的Send()方法对服务器端,可以使用客户端连接时创建的套接字发送数据,例如:……byte[]bytes=newbyte[1024];stringmessage=发送的数据;bytes=System.Text.Encoding.Unicode.GetBytes(message);clientSocket.Send(bytes,bytes.Length,SocketFlags.None);对客户端,用法相似,区别只是创建的套接字不同。12(2)使用NetworkStream类的Write()方法如果创建了NetworkStream对象,就可以直接使用该对象发送数据,例如服务器端代码可能类似于如下形式:NetworkStreamnetstream=newNetworkStream(clientSocket);stringmessage=发送的数据;byte[]bytes=System.Text.Encoding.Unicode.GetBytes(message);netstream.Write(bytes,0,bytes.Length);与套接字的Send()方法不同,NetworkStream对象的Write()方法返回值为void。134.接收数据与发送数据相似,接收数据的方法也有两种:使用Socket类的Receive方法或者使用NetworkStream类的Read方法,其用法与发送数据类似。例如:byte[]message=newbyte[1024];NetworkStreamnetstream=newNetworkStream(clientSocket);intlen=netstream.Read(message,0,message.Length);注意,Read()方法有一个整型的返回值,表明实际从TCP缓冲区中读取了多少字节的数据,这是因为有可能TCP缓冲区还没有接收到远程设备发送过来的指定长度的数据。145.TCP协议的无消息边界问题–TCP协议的无消息边界问题TCP协议是无消息边界的,即不能保证来自单个Send方法的数据能被单个Receive方法读取。–解决方法•发送固定长度的消息•将消息长度与消息一起发送•使用特殊标记分隔消息1510.4简单聊天程序•服务器端编程–创建windows应用程序项目TestSyncServer,设计画面如图所示–各控件属性参见表10-116“开始监听”的Click事件代码。privatevoidbuttonStart_Click(objectsender,System.EventArgse){this.buttonStart.Enabled=false;IPAddressip=IPAddress.Parse(this.textBoxIP.Text);IPEndPointserver=newIPEndPoint(ip,Int32.Parse(this.textBoxPort.Text));socket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);socket.Bind(server);socket.Listen(10);clientSocket=socket.Accept();this.listBoxState.Items.Add(与客户+clientSocket.RemoteEndPoint.ToString()+建立连接);thread=newThread(newThreadStart(AcceptMessage));thread.Start();}17privatevoidAcceptMessage(){while(true){try{NetworkStreamnetStream=newNetworkStream(clientSocket);byte[]datasize=newbyte[4];netStream.Read(datasize,0,4);intsize=System.BitConverter.ToInt32(datasize,0);Byte[]message=newbyte[size];intdataleft=size;intstart=0;while(dataleft0){intrecv=netStream.Read(message,start,dataleft);start+=recv;dataleft-=recv;}his.richTextBoxAccept.Rtf=System.Text.Encoding.Unicode.GetString(message);}catch{this.listBoxState.Items.Add(与客户断开连接);break;}}}18“停止监听”的Click事件代码。•privatevoidbuttonStop_Click(objectsender,System.EventArgse){•this.buttonStart.Enabled=true;•try{•socket.Shutdown(SocketShutdown.Both);•socket.Close();•if(clientSocket.Connected){•clientSocket.Close();thread.Abort();}}•catch{MessageBox.Show(监听尚未开始,关闭无效!);}}19添加“发送信息”的Click事件代码。privatevoidbuttonSend_Click(objectsender,System.EventArgse){stringstr=this.richTextBoxSend.Rtf;inti=str.Length;if(i==0){return;}else{//因为str为Unicode编码,每个字符占2字节,所以实际字节数应*2i*=2;}byte[]datasize=newbyte[4];datasize=System.BitConverter.GetBytes(i);byte[]sendbytes=System.Text.Encoding.Unicode.GetBytes(str);try{NetworkStreamnetStream=newNetworkStream(clientSocket);netStream.Write(datasize,0,4);netStream.Write(sendbytes,0,sendbytes.Length);netStream.Flush();this.richTextBoxSe
本文标题:第10章TCP协议开发
链接地址:https://www.777doc.com/doc-2241523 .html