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);//得到网络终结点
|
???TcpClient tcpClie
| ntA = new TcpClient(ipLocalE
| ndPoint);
|
| ???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对象实例
|
???tcpClient.Connect
| ("www.contoso.com",11002);//
| 建立连接
|
| ???Console.WriteLine(e.ToString()); |
??3、public TcpClien
上的指定端口。与前两个构
用Connect方法,其中strin
| t(string, int);初始化 TcpCli
造函数不一样,这个构造函数将
g类型的参数表示远程主机的Dns
| ent 类的新实例并连接到指定主机
自动建立连接,你不再需要额外调
名,如:www.tuha.net。
|
| ??以下示例语句调用这一方法实现与指定主机名和端口号的主机相连: |
???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对象实例
|
???s.Connect("www.tu
| ha.net",4088);//建立与远程主
| 机的连接
|
???MessageBox.show("
| 连接错误:" +e.Message);
|
???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对象实例
|
???tcpClient.Connect("www.tuha.n
| et",4088);//尝试与远程主机相连
|
| ???MessageBox.Show("连接错误:"+e.Message); |
???NetworkStream str
| eam=tcpClient.GetStream();//
| 获取网络传输流
|
???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 |
???TcpListener tcpLi
TcpListener对象实例以侦
| stener = new TcpListener(ipA
听用户端连接
| ddress, 4088);//创建
|
???MessageBox.Show("TcpListener
| 错误:"+e.Message);
|
??其次,当侦听到有用户端连接时,
一来完成连接:
| 需要接受挂起的连接请求,这通过调用以下两方法之
|
| ??public Socket AcceptSocket(); |
| ??public TcpClient AcceptTcpClient(); |
??前一个方法返回代表客户端的Sock
Receive 方法与远程计算机通讯;后一个
面介绍的 TcpClient.GetStream 方法获
用流读写Read/Write方法与远程计算机通
| et对象,随后可以通过Socket 类的 Send 和
方法返回代表客户端的TcpClient对象,随后使用上
取 TcpClient 的基础网络流 NetworkStream,并使
讯。
|
| ??最后,请记住关闭侦听器:public void Stop(); |
| ??同时关闭其他连接实例:public void Close(); |
???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());//预发送
|
???ns.Write(byteTime, 0, byteTim
| e.Length);//写入流
|
| ???client.Close();//关闭客户端连接 |
| ???MessageBox.Show("流错误:"+e.Message) |
????????综合运用上面的知识,下面
端和服务端分别编制了应用程序。客户端
信号,并发送交谈内容;远程主机端接收
时接收并显示客户端的交谈内容。在这个
于程序语言(C#)级的聊天室!
| 的实例实现了简单的网络通讯-双机互连,针对客户
创建到服务端的连接,向远程主机发送连接请求连接
来自客户的连接,向客户端发回确认连接的信号,同
基础上,发挥你的创造力,你完全可以开发出一个基
|
| ???public void SendMeg()//发送信息 |
??int port=Int32.Parse(textBox3.
| Text.ToString());//远程主机端口
|
???tcpClient=new TcpClient(textB
| ox1.Text,port);//创建TcpClient对象实例 }
|
???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);//写入流 |
| ???netStream.Close();//关闭网络流 |
| ???tcpClient.Close();//关闭客户端连接 |
???MessageBox.Show("
| Sending Message Failed!"+ex.
| Message);
|
???public void StartListen()//侦
| 听特定端口的用户请求
|
???int port=Int32.Parse(textBox1
| .Text.ToString());//本地待侦听端口
|
???serverListener=ne
| w TcpListener(port);//创建Tc
| pListener对象实例
|
| ???serverListener.Start(); //启动侦听 |
???MessageBox.Show("Can‘t Start
| Server"+ex.Message);
|
| ???while(true)//进入无限循环等待用户端连接 |
???tcpClient=serverListener.Acce
| ptTcpClient();//创建客户端连接对象
|
???netStream=tcpClie
| nt.GetStream();//得到网络流
|
???sr=new StreamReader(netStream
| );//流读写器
|
| ???MessageBox.Show(re.Message); |
| ???received+=sr.ReadLine();//读流中一行 |
| ???while(received.Length!=0) |
| ???received=sr.ReadLine(); |
| ??listBox1.Items.Add(buffer);//显示 |
上一页> 下一页>