分类

  • 软件天地

  • C#.Net 网络程序开发基础之TCP篇‖
    TCP/IP三层模型(请求响应
    于最底层的Socket类提供了
    理连接的细节,这使得我们
    UDPClient和TcpListener,

    程序开发-Socket篇》中说到:
    层、应用协议层、传输层)的中
    更高层次的抽象,它们封装 TCP
    在编写套接字级别的协议时,可
    而不是直接向 Socket 中写。它

    支持Http、Tcp和Udp的类组成了
    间层-应用协议层,该层的类比位
    和 UDP 套接字的创建,不需要处
    以更多地尝试使用 TCPClient 、
    们之间的这种层次关系示意如下:

      ???                                                                        
      ??可见, TcpClient
    服务的基础。正因为这样,
    件传输协议、HTTP(Hyperte
    TcpClient等类之上。
    类基于 Socket 类构建,这是它
    许多应用层上的通讯协议,比如
    xt Transfers Protocol)超文本

    能够以更高的抽象程度提供 TCP
    FTP(File Transfers Protocol)文
    传输协议等都直接创建在

      ???                                                                        
      ??TCPClient 类使用 T
    接,然后使用此连接发送和
    时以正确的顺序对其进行组
    CP 从 Internet 资源请求数据
    接收数据包。TCP 负责确保将数
    合。
    。TCP 协议建立与远程终结点的连
    据包发送到终结点并在数据包到达

      ???                                                                        
      ??从名字上就可以看出,TcpClient
    连接。TcpClient 提供了通过网络连接、
    类专为客户端设计,它为 TCP 网络服务提供客户端
    发送和接收数据的简单方法。
      ???                                                                        
      ??若要建立 TCP 连接,必须知道承
    务用于通讯的 TCP 端口 (Port)。Intern
    Authority, IANA) 定义公共服务的端口
    w.iana.org/assignments/port-numbers
    服务可使用 1,024 到 65,535 这一范围
    TcpClient类的三种构造函数之一:
    载所需服务的网络设备的地址(IPAddress)以及该服
    et 分配号码机构 (Internet Assigned Numbers
    号(你可以访问 http://ww
    获得这方面更详细的资料)。IANA 列表中所没有的
    中的端口号。要创建这种连接,你可以选用

      ???                                                                        
      ??1、public TcpClien
    地址并将使用默认的通信端
    。以下语句示例了如何使用
    t()当使用这种不带任何参数的
    口号0。这样情况下,如果本机
    默认构造函数来创建新的 TcpCl
    构造函数时,将使用本机默认的ip
    不止一个ip地址,将无法选择使用
    ient:
      ???                                                                        
      ??TcpClient tcpClientC = new Tcp
    Client();
      ???                                                                        
      ???                                                                        
      ??2、public TcpClien
    一篇介绍过了,IPEndPoint
    主机连接时所使用的本地网
    IPAddress和Port提供了选
    类的实例:
    t(IPEndPoint)使用本机IPEndPo
    将网络端点表示为IP地址和端口
    络接口(IP 地址)和端口号,
    择余地。下面的语句示例了如何

    int创建TcpClient的实例对象。上
    号,在这里它用于指定在建立远程
    这个构造方法为使用本机
    使用本地终结点创建 TcpClient

      ???                                                                        
      ??IPHostEntry ipInfo
    =Dns.GetHostByName("www.tuha
    .net");//主机信息
      ???IPAddressList[] i
    pList=ipInfo.AddressList;//I
    P地址数组
      ???IPAddress ip=ipList[0];//多IP
    地址时一般用第一个
      ???IPEndPoint ipEP=new IPEndPoin
    t(ip,4088);//得到网络终结点
      ???try{                                                               
      ???TcpClient tcpClie
    ntA = new TcpClient(ipLocalE
    ndPoint);
      ???}                                                                     
      ??catch (Exception e ) {                             
      ???Console.WriteLine(e.ToString());       
      ???}                                                                     
      ???                                                                        
      ???                                                                        
      ??到这里,你可能会感
    号应该是远程服务器的呀!
    TcpClient实例对象与IP地
    的连接,这可以通过TcpCli
    口号将客户端连接到 远程
    到困惑,客户端要和服务端创建
    事实上的确如此,使用以上两种
    址和Port端口的绑定,要完成连
    ent类的Connect方法来实现, C
    主机:
    连接,所指定的IP地址及通信端口
    构造函数,你所实现的只是
    接,你还需要显式指定与远程主机
    onnet方法使用指定的主机名和端

      ???                                                                        
      ??1)、public void Connect(IPEndP
    远程 TCP 主机。
    oint); 使用指定的远程网络终结点将客户端连接到

      ???                                                                        
      ??public void Connec
    到 TCP 主机。
    t(IPAddress, int); 使用指定

    的 IP 地址和端口号将客户端连接

      ???                                                                        
      ??public void Connec
    t(string, int); 将客户端连接
    到指定主机上的指定端口。
      ???                                                                        
      ??需要指出的是,Connect方法的所
    有重载形式中的参数IPEndPoint网络终
      ???                                                                        
      ??结点、IPAddress以
    务器。
    及表现为string的Dns主机名和i

    nt指出的Port端口均指的是远程服

      ???                                                                        
      ??以下示例语句使用主机默认IP和Port端口号0与远程主机建立连接:       
      ???                                                                        
      ??TcpClient tcpClient = new TcpC
    lient();//创建TcpClient对象实例
      ???try{                                                               
      ???tcpClient.Connect
    ("www.contoso.com",11002);//
    建立连接
      ???}                                                                     
      ???catch (Exception e ){                             
      ???Console.WriteLine(e.ToString());       
      ???}                                                                     
      ???                                                                        
      ???                                                                        
      ??3、public TcpClien
    上的指定端口。与前两个构
    用Connect方法,其中strin
    t(string, int);初始化 TcpCli
    造函数不一样,这个构造函数将
    g类型的参数表示远程主机的Dns
    ent 类的新实例并连接到指定主机
    自动建立连接,你不再需要额外调
    名,如:www.tuha.net。
      ???                                                                        
      ??以下示例语句调用这一方法实现与指定主机名和端口号的主机相连:             
      ???                                                                        
      ??try{                                                                 
      ???TcpClient tcpClientB = new Tc
    pClient("www.tuha.net", 4088);
      ???}                                                                     
      ???catch (Exception e ) {                           
      ???Console.WriteLine(e.ToString());       
      ???}                                                                     
      ??前面我们说,TcpClie
    体现在网络数据的发送和接
    据更加方便直观,同时,.N
    流具有更广泛的兼容性,构
    实际内容(HTML、XML 或其
    Stream.Read) 发送和接收
    时访问,可以在部分数据到
    .Net中通过NetworkStream
    nt类创建在Socket之上,在Tcp
    受方面,是TcpClient使用标准的
    et框架负责提供更丰富的结构来
    建在更一般化的流操作上的通用
    他任何内容),应用程序都将使
    数据。另外,流在数据从 Inter
    达时立即开始处理,而不需要等
    类实现了这些处理技术。
    服务方面提供了更高层次的抽象,
    Stream流处理技术,使得它读写数
    处理流,贯穿于整个.Net框架中的
    方法使我们不再需要困惑于文件的
    用一致的方法(Stream.Write、
    net 下载的过程中提供对数据的即
    待应用程序下载完整个数据集。

      ???                                                                        
      ??NetworkStream 类包含在.Net框架
    用于网络访问的基础数据流。NetworkStr
    .Net 框架流机制。NetworkStream 支持
    Stream 继承,后者提供了一组丰富的用
    的System.Net.Sockets 命名空间里,该类专门提供
    eam 实现通过网络套接字发送和接收数据的标准
    对网络数据流的同步和异步访问。NetworkStream 从
    于方便网络通讯的方法和属性。
      ???                                                                        
      ??同其它继承自抽象基类Stream的所
    数据通道,架设在数据来源端(客户Clien
    写入均针对这个通道来进行。
    有流一样,NetworkStream网络流也可以被视为一个
    t)和接收端(服务Server)之间,而后的数据读取及

      ???                                                                        
      ??.Net框架中,NetworkStream流支持两方面的操作:           
      ???                                                                        
      ??1、 写入流。写入是从数据结构到流的数据传输。                           
      ???                                                                        
      ??2、读取流。读取是从流到数据结构(如字节数组)的数据传输。               
      ???                                                                        
      ??与普通流Stream不同
    流的随机访问。相应属性Ca
    NotSupportedException。
    的是,网络流没有当前位置的统
    nSeek 始终返回 false,而 See

    一概念,因此不支持查找和对数据
    k 和 Position 方法也将引发

      ???                                                                        
      ??基于Socket上的应用
    流:
    协议方面,你可以通过以下两种

    方式获取NetworkStream网络数据

      ???                                                                        
      ??1、使用NetworkStream构造函数:
    bool);(有重载方法),它用指定的访问
    NetworkStream 类的新实例,使用前你
    法建立与远程服务端的连接,而后才可以
    public NetworkStream(Socket, FileAccess,
    权限和指定的 Socket 所属权为指定的 Socket 创建
    需要创建Socket对象实例,并通过Socket.Connect方
    使用该方法得到网络传输流。示例如下:
      ???                                                                        
      ??Socket s=new Socket(AddressFam
    ype.Stream,ProtocolType.Tcp);//创建
    ily.InterNetwork,SocketT
    客户端Socket对象实例
      ???try{                                                               
      ???s.Connect("www.tu
    ha.net",4088);//建立与远程主
    机的连接
      ???}                                                                     
      ???catch(Exception e){                                 

      ???MessageBox.show("
    连接错误:" +e.Message);
      ???}                                                                     
      ???try{                                                               
      ???NetworkStream str
    网络传输流
    eam=new NetworkStream(s,File

    Access.ReadWrite,false);//取得

      ???}                                                                     
      ???                                                                        
      ???                                                                        
      ??2、通过TcpClient.G
    送和接收数据的基础网络流
    数参数来创建 NetworkStre
    程主机的连接,示例如下:
    etStream方法:public Network
    NetworkStream。GetStream 通
    am 类的实例。使用前你需要先

    Stream etStream();它返回用于发
    过将基础 Socket 用作它的构造函
    创TcpClient对象实例并建立与远

      ???                                                                        
      ??TcpClient tcpClien
    t = new TcpClient();//创建Tc
    pClient对象实例
      ???Try{                                                               
      ???tcpClient.Connect("www.tuha.n
    et",4088);//尝试与远程主机相连
      ???}                                                                     
      ???catch(Exception e){                                 
      ???MessageBox.Show("连接错误:"+e.Message);
      ???}                                                                     
      ???try{                                                               
      ???NetworkStream str
    eam=tcpClient.GetStream();//
    获取网络传输流
      ???}                                                                     
      ???catch(Exception e)                                   
      ???{                                                                     
      ???MessageBox.Show("
    TcpClient错误:"+e.Message);

      ???}                                                                     
      ???                                                                        
      ???                                                                        
      ??通过以上方法得到NetworkStream
    Read来发送和接受数据了。
    网络流之后,你就可以使用标准流读写方法Write和

      ???                                                                        
      ??以上是.Net下使用Tc
    务,我们还需要编制相应的
    曾经提到, Socket作为其
    发,在传输层面上使用较多
    TcpClient取代Socket;相
    TCP 服务,使得我们能更方
    这样的应用层协议都是在 T
    pClient类实现客户端编程的技
    服务端程序,前一篇《Visual C
    他网络协议的基础,既可以面向
    ,而在应用协议层面上,客户端
    应地,构建于Socket之上的TcpL
    便地编写服务端应用程序。正是
    cpListener 类的基础上建立的
    术资料,为了向客户端提供这些服
    #.Net网络程序开发-Socket篇》上
    客户端开发,也可以面向服务端开
    我们采用构建于Socket类之上的
    istener提供了更高理念级别的
    因为这样的原因,像FTP 和 HTTP

      ???                                                                        
      ??.Net中的TCPListener 用于监视TC
    口(这两者应与客户端的请求一致)创建
    TcpListener侦听到用户端的连接后,视
    接受传入的连接请求并创建 TcpClient
    的连接请求并创建 Socket 以处理请求。
    Socket,你必须也关闭从 AcceptSocket
    细解说如下:
    P 端口上的传入请求,通过绑定本机IP地址和相应端
    TcpListener对象实例,并由Start方法启动侦听;当
    客户端的不同请求方式,通过AcceptTcpClient 方法
    以处理请求,或者通过AcceptSocket 方法接受传入
    最后,你需要使用 Stop 关闭用于侦听传入连接的
    或 AcceptTcpClient 返回的任何实例。这个过程详

      ???                                                                        
      ??首先,创建TcpListe
    ner对象实例,这通过TcpListen
    er类的构造方法来实现:
      ???                                                                        
      ??public TcpListener(port);//指定本机端口       
      ??public TcpListener
    (IPEndPoint)//指定本机终结点

      ??public TcpListener(IPAddress,p
    ort)//指定本机IP地址及端口
      ???                                                                        
      ???                                                                        
      ??以上方法中的参数在
    对服务端主机。下面的示例
    前面多次提到,这里不再细述,
    演示创建 TcpListener 类的实
    唯一需要提醒的是,这些参数均针
    例:
      ???                                                                        
      ??IPHostEntry ipInfo=Dns.Resolve
    ("127.0.0.1");//主机信息
      ???IPAddressList[] ipList=ipInfo
    .IPAddressList;//IP数组
      ???IPAddress ip=ipList[0];//IP                 
      ???try{                                                               
      ???TcpListener tcpLi
    TcpListener对象实例以侦
    stener = new TcpListener(ipA
    听用户端连接
    ddress, 4088);//创建

      ???}                                                                     
      ???catch ( Exception e){                             
      ???MessageBox.Show("TcpListener
    错误:"+e.Message);
      ???}                                                                     
      ???                                                                        
      ???                                                                        
      ??随后,你需要调用Start方法启动侦听:                                 
      ???                                                                        
      ??public void Start();                                 
      ???                                                                        
      ???                                                                        
      ??其次,当侦听到有用户端连接时,
    一来完成连接:
    需要接受挂起的连接请求,这通过调用以下两方法之

      ???                                                                        
      ??public Socket AcceptSocket();               
      ??public TcpClient AcceptTcpClient();   
      ???                                                                        
      ???                                                                        
      ??前一个方法返回代表客户端的Sock
    Receive 方法与远程计算机通讯;后一个
    面介绍的 TcpClient.GetStream 方法获
    用流读写Read/Write方法与远程计算机通
    et对象,随后可以通过Socket 类的 Send 和
    方法返回代表客户端的TcpClient对象,随后使用上
    取 TcpClient 的基础网络流 NetworkStream,并使
    讯。
      ???                                                                        
      ??最后,请记住关闭侦听器:public void Stop();           
      ???                                                                        
      ??同时关闭其他连接实例:public void Close();           
      ???                                                                        
      ??下面的示例完整体现了上面的过程:                                         
      ???                                                                        
      ??bool done = false;                                     
      ???TcpListener listener = new Tc
    端口提供时间服务)
    pListener(13);// 创建TcpListener对象实例(13号

      ???listener.Start();//启动侦听                         
      ???while (!done) {//进入无限循环以侦听用户连接           
      ???TcpClient client = listener.A
    TcpClient
    cceptTcpClient();//侦听到连接后创建客户端连接

      ???NetworkStream ns
    = client.GetStream();//得到
    网络传输流
      ???byte[] byteTime =
    的内容(此为服务端时间)转
    Encoding.ASCII.GetBytes(Dat
    换为字节数组以便写入流
    eTime.Now.ToString());//预发送

      ???try {                                                             
      ???ns.Write(byteTime, 0, byteTim
    e.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(textB
    ox1.Text,port);//创建TcpClient对象实例 }
      ???catch(Exception le)                                 
      ???{                                                                     
      ???MessageBox.Show("
    TcpClient Error:"+le.Message
    );
      ???}                                                                     
      ??string strDateLine=DateTime.No
    "+DateTime.Now.ToLongTimeString();//
    w.ToShortDateString()+"
    得到发送时客户端时间
      ???netStream=tcpClient.GetStream
    ();//得到网络流
      ???sw=new StreamWrit
    er(netStream);//创建TextWrit
    er,向流中写字符
      ???string words=textBox4.Text;//待发送的话   
      ???string content=strDateLine+wo
    rds;//待发送内容
      ???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=ne
    w TcpListener(port);//创建Tc
    pListener对象实例
      ???serverListener.Start(); //启动侦听           
      ???}                                                                     
      ???catch(Exception ex)                                 
      ???{                                                                     
      ???MessageBox.Show("Can‘t Start
    Server"+ex.Message);
      ???return;                                                         
      ???}                                                                     
      ???isLinked=true;                                           
      ???while(true)//进入无限循环等待用户端连接                   
      ???{                                                                     
      ???try                                                                 
      ???{                                                                     
      ???tcpClient=serverListener.Acce
    ptTcpClient();//创建客户端连接对象

      ???netStream=tcpClie
    nt.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+="rn";                                         
      ???//received="";                                           
      ???received=sr.ReadLine();                         
      ???}                                                                     
      ??listBox1.Items.Add(buffer);//显示           
      ??//关闭                                                                 
      ??sr.Close();                                                   
      ??netStream.Close();                                     
      ??tcpClient.Close();                                     
      ??}                                                                       
      ??}?                                                                      

    上一页 下一页




    map