博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

TCP协议C#

Posted on 2008-07-02 18:46  懒人ABC  阅读(740)  评论(0编辑  收藏  举报
 

Visual C#.Net程序开-Socket篇》中:支持HttpTcpUdp类组成了TCP/IP模型(求响应层协议层传输层)的中间层-协议层该层比位于最底Socket提供了更高次的抽象,它封装 TCP UDP 套接字的建,不需要接的细节使得我写套接字级别协议时,可以更多地尝试使用 TCPClient UDPClientTcpListener,而不是直接向 Socket 中写。它次关系示意如下: TcpClient 基于 Socket 构建,是它能以更高的抽象程度提供 TCP 的基。正因为这样上的通讯协议,比如FTP(File Transfers Protocol)文件传输协议HTTP(Hypertext Transfers Protocol)超文本传输协议等都直接建在TcpClient之上。 TCPClient 使用 TCP Internet 求数据。TCP 协议建立与终结点的接,然后使用此送和接收数据包。TCP 负责确保将数据包送到终结点并在数据包到达以正确的合。从名字上就可以看出,TcpClient类专为设计,它 TCP 提供客接。TcpClient 提供了通络连接、送和接收数据的简单方法。若要建立 TCP 接,必知道承所需服的网络设备的地址(IPAddress)以及用于通 TCP 端口 (Port)Internet 分配号机构 (Internet Assigned Numbers Authority, IANA) 公共服的端口号(你可以访问 http://www.iana.org/assignments/port-numbers方面更详细料)。IANA 列表中所没有的服可使用 1,024 65,535 一范中的端口号。要接,你可以TcpClient的三种构造函数之一: 1public TcpClient()当使用种不任何参数的构造函数,将使用本机默ip地址并将使用默的通信端口号0这样情况下,如果本机不止一个ip地址,将无法选择使用。以下句示例了如何使用默构造函数来建新的 TcpClient TcpClient tcpClientC = new TcpClient(); 2public TcpClient(IPEndPoint)使用本机IPEndPointTcpClient象。上一篇介绍过了,IPEndPoint将网端点表示IP地址和端口号,在里它用于指定在建立程主机所使用的本地网接口(IP 地址)和端口号,个构造方法使用本机IPAddressPort提供了选择余地。下面的句示例了如何使用本地终结 TcpClient 例: IPHostEntry ipInfo=Dns.GetHostByName("www.tuha.net");//主机信息 IPAddressList[] ipList=ipInfo.AddressList;//IP地址数 IPAddress ip=ipList[0];//IP地址一般用第一个 IPEndPoint ipEP=new IPEndPoint(ip,4088);//得到网络终结 try{ TcpClient tcpClientA = new TcpClient(ipLocalEndPoint); } catch (Exception e ) { Console.WriteLine(e.ToString()); } 里,你可能会感到困惑,客端要和服接,所指定的IP地址及通信端口号应该程服器的呀!事上的确如此,使用以上两种构造函数,你所实现的只是TcpClient象与IP地址和Port端口的定,要完成接,你需要式指定与程主机的接,可以通TcpClientConnect方法来实现 Connet方法使用指定的主机名和端口号将客接到程主机: 1)public void Connect(IPEndPoint); 使用指定的程网络终结点将客接到 TCP 主机。public void Connect(IPAddress, int); 使用指定的 IP 地址和端口号将客接到 TCP 主机。 public void Connect(string, int); 将客接到指定主机上的指定端口。需要指出的是,Connect方法的所有重形式中的参IPEndPoint络终点、IPAddress以及表现为stringDns主机名和int指出的Port端口均指的是程服器。以下示例句使用主机默IPPort端口号0程主机建立接: TcpClient tcpClient = new TcpClient();//TcpClient try{ tcpClient.Connect("www.contoso.com",11002);//建立 } catch (Exception e ){ Console.WriteLine(e.ToString()); } 3public TcpClient(string, int);初始化 TcpClient 的新例并接到指定主机上的指定端口。与前两个构造函数不一个构造函数将自建立接,你不再需要Connect方法,其中string型的参数表示程主机的Dns名,如:www.tuha.net以下示例一方法实现与指定主机名和端口号的主机相 try{ TcpClient tcpClientB = new TcpClient("www.tuha.net", 4088); } catch (Exception e ) { Console.WriteLine(e.ToString()); }     

前面我们说,TcpClient类创建在Socket之上,在Tcp方面提供了更高次的抽象,在网数据的送和接受方面,TcpClient使用准的Stream理技,使得它写数据更加方便直,同.Net框架负责提供更丰富的构来理流,穿于整个.Net框架中的流具有更广泛的兼容性,构建在更一般化的流操作上的通用方法使我不再需要困惑于文件的实际内容(HTMLXML 或其他任何内容),用程序都将使用一致的方法(Stream.WriteStream.Read送和接收数据。另外,流在数据从 Internet 程中提供数据的即时访问,可以在部分数据到达立即开始理,而不需要等待用程序下完整个数据集。.Net中通NetworkStream类实现理技 NetworkStream 包含在.Net框架的System.Net.Sockets 命名空里,该类专门提供用于网络访问的基数据流。NetworkStream 实现套接字送和接收数据的.Net 框架流机制。NetworkStream 支持数据流的同步和异步访问NetworkStream Stream 承,后者提供了一丰富的用于方便网的方法和属性。同其它承自抽象基Stream的所有流一NetworkStream流也可以被视为一个数据通道,架在数据来源端(Client)和接收端(服Server)之,而后的数据取及写入均针对这个通道来行。 .Net框架中,NetworkStream流支持两方面的操作: 1写入流。写入是从数据构到流的数据传输 2取流。取是从流到数据构(如字的数据传输与普通流Stream不同的是,网流没有当前位置的一概念,因此不支持找和数据流的随机访问。相属性CanSeek 返回 false,而 Seek Position 方法也将引 NotSupportedException基于Socket上的协议方面,你可以通以下两种方式NetworkStream数据流: 1、使用NetworkStream构造函数:public NetworkStream(Socket, FileAccess, bool);(有重法),它用指定的访问权限和指定的 Socket 所属权为指定的 Socket NetworkStream 的新例,使用前你需要Socket例,并通Socket.Connect方法建立与程服端的接,而后才可以使用方法得到网络传输流。示例如下: Socket s=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);//建客Socket try{ s.Connect("www.tuha.net",4088);//建立与程主机的 } catch(Exception e){ MessageBox.show("错误" +e.Message); } try{ NetworkStream stream=new NetworkStream(s,FileAccess.ReadWrite,false);//取得网络传输 } 2、通TcpClient.GetStream方法:public NetworkStream etStream();它返回用于送和接收数据的基NetworkStreamGetStream 将基 Socket 用作它的构造函数参数来 NetworkStream 例。使用前你需要先TcpClient例并建立与程主机的接,示例如下: TcpClient tcpClient = new TcpClient();//TcpClient Try{ tcpClient.Connect("www.tuha.net",4088);//尝试程主机相 } catch(Exception e){ MessageBox.Show("错误:"+e.Message); } try{ NetworkStream stream=tcpClient.GetStream();//取网络传输 } catch(Exception e) { MessageBox.Show("TcpClient错误"+e.Message); } 以上方法得到NetworkStream流之后,你就可以使用准流写方法WriteRead送和接受数据了。以上是.Net下使用TcpClient类实现程的技术资料,了向客端提供些服,我们还需要制相的服端程序,前一篇《Visual C#.Net程序开-Socket篇》上曾提到, Socket其他网络协议的基,既可以面向客端开,也可以面向服端开,在传输层面上使用多,而在协议层面上,客端我采用构建于Socket之上的TcpClient取代Socket;相地,构建于Socket之上的TcpListener提供了更高理念级别 TCP ,使得我能更方便地写服用程序。正是因为这样的原因,像FTP HTTP 这样层协议都是在 TcpListener 的基上建立的。 .Net中的TCPListener 用于监视TCP 端口上的求,通过绑定本机IP地址和相端口(两者与客端的求一致)TcpListener,并由Start方法启动侦听;当TcpListener听到用端的接后,端的不同求方式,通AcceptTcpClient 方法接受入的求并 TcpClient 求,或者通AcceptSocket 方法接受入的求并 Socket 求。最后,你需要使用 Stop 用于接的 Socket,你必也关 AcceptSocket AcceptTcpClient 返回的任何例。详细如下:首先,TcpListener例,TcpListener的构造方法来实现 public TcpListener(port);//指定本机端口 public TcpListener(IPEndPoint)//指定本机终结 public TcpListener(IPAddress,port)//指定本机IP地址及端口以上方法中的参数在前面多次提到,里不再述,唯一需要提醒的是,些参数均针对端主机。下面的示例演示 TcpListener 例: IPHostEntry ipInfo=Dns.Resolve("127.0.0.1");//主机信息 IPAddressList[] ipList=ipInfo.IPAddressList;//IP IPAddress ip=ipList[0];//IP try{ TcpListener tcpListener = new TcpListener(ipAddress, 4088);//TcpListener例以听用 } catch ( Exception e){ MessageBox.Show("TcpListener错误"+e.Message); } 随后,你需要Start方法启动侦听: public void Start(); 其次,当听到有用,需要接受挂起的求,过调用以下两方法之一来完成接: public Socket AcceptSocket(); public TcpClient AcceptTcpClient(); 前一个方法返回代表客端的Socket象,随后可以通Socket Send Receive 方法与算机通;后一个方法返回代表客端的TcpClient象,随后使用上面介 TcpClient.GetStream 方法 TcpClient 的基 NetworkStream,并使用流Read/Write方法与算机通最后,请记住关闭侦听器:public void Stop(); 其他例:public void Close(); 下面的示例完整体上面的程: bool done = false; TcpListener listener = new TcpListener(13);// TcpListener(13号端口提供时间) listener.Start();//动侦 while (!done) {//入无限循听用户连 TcpClient client = listener.AcceptTcpClient();//听到接后建客TcpClient NetworkStream ns = client.GetStream();//得到网络传输 byte[] byteTime = Encoding.ASCII.GetBytes(DateTime.Now.ToString());//预发送的内容(时间)转换为以便写入流 try { ns.Write(byteTime, 0, byteTime.Length);//写入流 ns.Close();// client.Close();// } catch (Exception e) { MessageBox.Show("错误:"+e.Message) }

合运用上面的知,下面的实现简单的网-双机互针对端和服端分别编制了用程序。客建到服端的接,向程主机接信号,并送交内容;程主机端接收来自客接,向客回确认连接的信号,同接收并示客端的交内容。在个基上,发挥你的造力,你完全可以开出一个基于程序(C#)的聊天室!端主要源代 public void SendMeg()//送信息 { try { int port=Int32.Parse(textBox3.Text.ToString());//程主机端口 try { tcpClient=new TcpClient(textBox1.Text,port);//TcpClient } catch(Exception le) { MessageBox.Show("TcpClient Error:"+le.Message); } string strDateLine=DateTime.Now.ToShortDateString()+" "+DateTime.Now.ToLongTimeString();//得到时间 netStream=tcpClient.GetStream();//得到网 sw=new StreamWriter(netStream);//TextWriter,向流中写字符 string words=textBox4.Text;//送的 string content=strDateLine+words;//送内容 sw.Write(content);//写入流 sw.Close();//流写入 netStream.Close();// tcpClient.Close();// } catch(Exception ex) { MessageBox.Show("Sending Message Failed!"+ex.Message); } textBox4.Text="";//清空 } 器端主要源代 public void StartListen()//听特定端口的用户请 { //ReceiveMeg(); isLinked=false; // try { int port=Int32.Parse(textBox1.Text.ToString());//本地待听端口 serverListener=new TcpListener(port);//TcpListener serverListener.Start(); //动侦 } catch(Exception ex) { MessageBox.Show("Can't Start Server"+ex.Message); return; } isLinked=true; while(true)//入无限循等待用 { try { tcpClient=serverListener.AcceptTcpClient();//建客 netStream=tcpClient.GetStream();//得到网 sr=new StreamReader(netStream);//写器 } catch(Exception re) { MessageBox.Show(re.Message); } string buffer=""; string received=""; received+=sr.ReadLine();//流中一行 while(received.Length!=0) { buffer+=received; buffer+=""r"n"; //received=""; received=sr.ReadLine(); } listBox1.Items.Add(buffer);// // sr.Close(); netStream.Close(); tcpClient.Close(); } }