Cnrd+net20+套接字编程实例+UDP+TCP通信nrd

C# t2.00 套接接字编程程实例 UDPP TCCP通信信 首首先从原原理上解解释一下下采用SSockket接接口的网网络通讯讯,这里里以最常常用的CC/S模模式作为为范例,首首先,服服务端有有一个进进程(或或多个进进程)在在指定的的端口等等待客户户来 连连接,服服务程序序等待客客户的连连接信息息,一旦旦连接上上之后,就就可以按按设计的的数据交交换方法法和格式式进行数数据传输输客户户端在需需要的时时刻发出出向服务务端的连连接请求求这里里为 了了便于理理解,提提到了一一些调用用及其大大致的功功能使使用soockeet调用用后,仅仅产生了了一个可可以使用用的soockeet描述述符,这这时还不不能进行行通信,还还要使用用其他的的调 用用,以使使得soockeet所指指的结构构中使用用的信息息被填写写完 在使使用TCCP协议议时,一一般服务务端进程程先使用用socckett调用得得到一个个描述符符,然后后使用bbindd调用将将一个名名字 与与socckett描述符符连接起起来,对对于Innterrnett域就是是将Innterrnett地址联联编到ssockket。
之之后,服服务端使使用liisteen调用用指出等等待服务务请 求求队列的的长度然然后就可可以使用用accceptt调用等等待客户户端发起起连接,一一般是阻阻塞等待待连接,一一旦有客客户端发发出连接接,accceppt返回回客户的的地址信信息,并并返回 一个新新的soockeet描述述符,该该描述符符与原先先的soockeet有相相同的特特性,这这时服务务端就可可以使用用这个新新的soockeet进行行读写操操作了一一般服务务端可能能在 aacceept返返回后创创建一个个新的进进程进行行与客户户的通信信,父进进程则再再到accceppt调用用处等待待另一个个连接客客户端进进程一般般先使用用socckett调用得得到一个个 soockeet描述述符,然然后使用用connnecct向指指定的服服务器上上的指定定端口发发起连接接,一旦旦连接成成功返回回,就说说明已经经建立了了与服务务器的连连接,这这时就可可以通过过 soockeet描述述符进行行读写操操作了 .NNetFFrammeWoork为为Socckett通讯提提供了SSysttem..Nett.Soockeet命名名空间,在在这个命命名空间间里面有有以下几几个常用用的重要要类分别别是: ·SSockket类类这个低低层的类类用于管管理连接接,WeebReequeest,TTcpCClieent和和UdppCliientt在内部部使用这这个类。
·NNetwworkkStrreamm类这个个类是从从Strreamm派生出出来的,它它表示来来自网络络的数据据流 ·TTcpCClieent类类允许创创建和使使用TCCP连接接 ·TTcpLListteneer类允允许监听听传入的的TCPP连接请请求 ·UUdpCClieent类类用于UUDP客客户创建建连接((UDPP是另外外一种TTCP协协议,但但没有得得到广泛泛的使用用,主要要用于本本地网络络) 下面面我们来来看一个个基于SSockket的的双机通通信代码码的C##版本 首先先创建SSockket对对象的实实例,这这可以通通过Soockeet类的的构造方方法来实实现:publlic Socckett(AdddreessFFamiily adddresssFaamilly,SSockketTTypee soockeetTyype,,ProotoccolTTypee prrotoocollTyppe);; 其中中,adddreessFFamiily 参数指指定 SSockket 使用的的寻址方方案,ssockketTTypee 参数数指定 Socckett 的类类型,pprottocoolTyype 参数指指定 SSockket 使用的的协议。
下面面的示例例语句创创建一个个 Soockeet,它它可用于于在基于于 TCCP/IIP 的的网络(如如 Innterrnett)上通通讯Sockket temmp == neew SSockket((AdddresssFaamilly.IInteerNeetwoork,, SoockeetTyype..Strreamm, PProttocoolTyype..Tcpp); 若要要使用 UDPP 而不不是 TTCP,需需要更改改协议类类型,如如下面的的示例所所示:Sockket temmp == neew SSockket((AdddresssFaamilly.IInteerNeetwoork,, SoockeetTyype..Dgrram,, PrrotoocollTyppe.UUdp)); 一旦旦创建 Socckett,在客客户端,你你将可以以通过CConnnectt方法连连接到指指定的服服务器(你你可以在在Connnecct方法法前Biind端端口,就就是以指指定的端端口发起起连接,如如 果不不事先BBindd端口号号的话,系系统会默默认在110244到50000随随机绑定定一个端端口号),并并通过SSendd方法向向远程服服务器发发送数据据,而后后可以通通过 RReceeivee从服务务端接收收数据;;而在服服务器端端,你需需要使用用Binnd方法法绑定所所指定的的接口使使Socckett与一个个本地终终结点相相联,并并通过LListten方方法侦 听该接接口上的的请求,当当侦听到到用户端端的连接接时,调调用Accceppt完成成连接的的操作,创创建新的的Socckett以处理理传入的的连接请请求。
使使用完 Socckett 后,使使用 CClosse 方方法关闭闭 Soockeet 可以以看出,以以上许多多方法包包含EnndPoointt类型的的参数,在在Intternnet中中,TCCP/IIP 使使用一个个网络地地址和一一个服务务端口号号来唯一一标识设设备网网络地址址标识网网络上的的特定设设备;端端口号标标识要连连接到的的该设备备上的特特定服务务网络络地址和和服务端端口的组组合称 为终结结点,在在 .NNET 框架中中正是由由 EnndPoointt 类表表示这个个终结点点,它提提供表示示网络资资源或服服务的抽抽象,用用以标志志网络地地址等信信息Nett同时也也为每个个受支持持的地址址族定义义了 EEndPPoinnt 的的子代;;对于 IP 地址族族,该类类为 IIPEnndPoointtIPPEnddPoiint 类包含含应用程程序连接接到主机机上的服服务所需需的主机机和端口口信息,通通过组合合服务的的主机IIP地址址和端口口号,IIPEnndPoointt 类形形成到服服务的连连接点 用到到IPEEndPPoinnt类的的时候就就不可避避免地涉涉及到计计算机IIP地址址,Syysteem.NNet命命名空间间中有两两种类可可以得到到IP地地址实例例: ·IIPAdddreess类类:IPPAdddresss 类类包含计计算机在在 IPP 网络络上的地地址。
其其Parrse方方法可将将 IPP 地址址字符串串转换为为 IPPAdddresss 实实例下下面的语语句创建建一个 IPAAddrresss 实例例:IPAdddreess myIIP == IPPAdddresss.PParsse(""1922.1668.00.1""); 需要要知道的的是:SSockket 类支持持两种基基本模式式:同步步和异步步其区区别在于于:在同同步模式式中,按按块传输输,对执执行网络络操作的的函数(如如 Seend 和 RReceeivee)的调调用一直直等到所所有内容容传送操操作完成成后才将将控制返返回给调调用程序序在异异步模式式中,是是按位传传输,需需要指定定发送的的开始和和结束同同步模式式是最常常用 的的模式,我我们这里里的例子子也是使使用同步步模式 下面面看一个个完整的的例子,cclieent向向serrverr发送一一段测试试字符串串,seerveer接收收并显示示出来,给给予clliennt成功功响应//clliennt端uusinng SSysttem;;usiing Sysstemm.Teext;;usiing Sysstemm.IOO;ussingg Syysteem.NNet;;usiing Sysstemm.Neet.SSockketss;naamesspacce ssockketssampple{{claass Claass11{staaticc vooid Maiin()){tryy{intt poort = 220000;sttrinng hhostt = "1227.00.0..1";;IPAAddrresss ipp = IPAAddrresss.Paarsee(hoost));IPPEnddPoiint ipee = neww IPPEnddPoiint((ip,, poort));///把ipp和端口口转化为为IPEEndPPoinnt实例例Socckett c = nnew Socckett(AdddreessFFamiily..IntterNNetwworkk, SSockketTTypee.Sttreaam, ProotoccolTTypee.Tccp);;//创创建一个个SocckettConnsolle.WWritteLiine(("Coonneetinng...."));c..Connnecct(iipe));///连接到到服务器器strringg seendSStr = ""helllo!!Thiis iis aa soockeet ttestt";bbytee[] bs = EEncoodinng.AASCIII.GGetBBytees(ssenddStrr);CConssolee.WrriteeLinne(""Sennd MMesssagee");;c.SSendd(bss, bbs.LLenggth,, 0));///发送测测试信息息strringg reecvSStr = """;bbytee[] reccvByytess = neww byyte[[10224];;intt byytess;byytess = c.RReceeivee(reecvBBytees, reccvByytess.Leengtth, 0);;//从从服务器器端接受受返回信信息reecvSStr += Enccodiing..ASCCII..GettStrringg(reecvBBytees, 0, byttes));Coonsoole..WriiteLLinee("CClieent Gett Meessaage::{0}}", reccvSttr);;//显显示服务务器返回回信息cc.Cllosee();;}cattch (ArrgummenttNulllExxcepptioon ee){Conssolee.WrriteeLinne(""ArggumeentNNulllExccepttionn: {{0}"", ee);}}cattch (SoockeetExxcepptioon ee){Connsolle.WWritteLiine(("SoockeetExxcepptioon: {0}}", e);;}Connsolle.WWritteLiine(("Prresss Ennterr too Exxit"");CConssolee.ReeadLLinee();;}}}//sservver端端usiing Sysstemm;ussingg Syysteem.TTextt;ussingg Syysteem.IIO;uusinng SSysttem..Nett;ussingg Syysteem.NNet..Soccketts;nnameespaace Proojecct1{{claass Claass22{staaticc vooid Maiin()){tryy{intt poort = 220000;sttrinng hhostt = "1227.00.0..1";;IPAAddrresss ipp = IPAAddrresss.Paarsee(hoost));IPPEnddPoiint ipee = neww IPPEnddPoiint((ip,, poort));Soockeet ss = neww Soockeet(AAddrresssFammilyy.InnterrNettworrk, SocckettTyppe.SStreeam,, PrrotoocollTyppe.TTcp));///创建一一个Soockeet类ss.Biind((ipee);///绑定定20000端口口s.LListten((0);;//开开始监听听Connsolle.WWritteLiine(("Waait forr coonneect"");SSockket temmp == s..Accceptt();;//为为新建连连接创建建新的SSockket。
Console.WriteLine("Get a connect");string recvStr = "";byte[] recvBytes = new byte[1024];int bytes;bytes = temp.Receive(recvBytes, recvBytes.Length, 0);//从客户端接受信息recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);Console.WriteLine("Server Get Message:{0}",recvStr);//把客户端传来的信息显示出来string sendStr = "Ok!Client Send Message Sucessful!";byte[] bs = Encoding.ASCII.GetBytes(sendStr);temp.Send(bs, bs.Length, 0);//返回客户端成功信息temp.Close();s.Close();}catch (ArgumentNullException e){Console.WriteLine("ArgumentNullException: {0}", e);}catch (SocketException e){Console.WriteLine("SocketException: {0}", e);}Console.WriteLine("Press Enter to Exit");Console.ReadLine();}}} 上面面的例子子是用的的Socckett类,SSysttem..Nett.Soockeet命名名空间还还提供了了两个抽抽象高级级类TCCPClliennt和UUDPCClieent和和用于通通讯流处处理的NNetWWorkkStrreamm,让我我们看下下例子 客户户端TcpCClieent tcppCliientt=neew TTcpCCLieent((主机IIP,端端口号));NeetwoorkSStreeam ns==tcpp.Clliennt.GGetSStreeam((); 服务务端TcpLListteneer ttcpLListteneer=nnew TcppLisstenner((监听端端口);;tcppLisstenner..Staart(();TTcpCClieent tcppCliientt=tccpLiisteenerr.AcccepptTccpClliennt());NeetwoorkSStreeam ns==tcppCliientt.GeetSttreaam()); 服务务端用TTcpLListteneer监听听,然后后把连接接的对象象实例化化为一个个TcppCliientt,调用用TcppCliientt.GeetSttreaam())方法,,返回网网络流实实例化为为一个NNetwworllStrreamm流,下下面就是是用流的的方法进进行Seend,,Recceivve 如果果是UddpClliennt的话话,就直直接UddpClliennt实例例化,然然后调用用UdppCliientt的Seend和和 Reeceiive方方法,需需要注意意的事,,UdppCliientt没有返返回网络络流的方方法,就就是说没没有GeetSttreaam方法法,所以以无法流流化,而而且使用用Udpp通信的的时 候候,不要要服务器器监听。
现在在我们大大致了解解了.NNet Socckett通信的的流程,下下面我们们来作一一个稍微微复杂点点的程序序,一个个广播式式的C//S聊天天程序客户端设设计需要要一个11个LiistBBox,用用于显示示聊天内内容,一一个TeextBBox输输入你要要说的话话,一个个Butttonn发送留留言,一一个Buuttoon建立立连接 点击击建立连连接的BButtton后后出来一一个对话话框,提提示输入入连接服服务器的的IP,端端口,和和你的昵昵称,启启动一个个接受线线程,负负责接受受从服务务器传来来的信息息并显示示在LiistBBox上上面 服务务器端22个Buuttoon,一一个启动动服务,一一个T掉掉已建立立连接的的客户端端,一个个LisstBoox显示示连接上上的客户户端的IIp和端端口 比较较重要的的地方是是字符串串编码的的问题,需需要先把把需要传传送的字字符串按按照UTTF8编编码,然然后接受受的时候候再还原原成为GGB23312,不不然中文文显示会会是乱码码 还有有一个就就是接收收线程,我我这里简简单写成成一个WWhille(tturee)循环环,不断断判断是是否有信信息流入入,有就就接收,并并显示在在LisstBoox上,这这里有问问题,在在.Neet2..0里面面,交错错线程修修改窗体体空间属属性的时时候会引引发一个个异常,不不可以直直接修改改,需要要定义一一个委托托来修改改。
当客客户端需需要断开开连接的的时候,比比如点击击窗体右右上角的的XX,就就需要定定义一个个thiis.FFormmCloosinng ++= nnew Sysstemm.Wiindoows..Forrms..ForrmCllosiingEEvenntHaandller((thiis.CClossingg);(..Nett2.00是 FFormmCloosinng系统统事件),在在Cloosinng())函数里里面,发发送Cllosee字符给给服务端端,服务务器判断断循环判判断所有有的连接接上的客客户端传传来的信信息,如如 果是是以Cllosee开头,断断开与其其的连接接看到到这里,读读者就会会问了,如如果我在在聊天窗窗口输入入Cloose是是不是也也断开连连接呢??不是的的,在聊聊天窗口口输入的的信息传传给 服服务器的的时候开开头都要要加上IIp信息息和昵称称,所以以不会冲冲突。