TCPClient、TCPListener的用法
支持Http、Tcp和Udp的类组成了TCP/IP三层模型(请求响应层、应用协议层、传输层)的中间层-应用协议层,该层的类比位于最底层的Socket类提供了更高层次的抽象,它们封装 TCP 和 UDP 套接字的创建,不需要处理连接的细节,这使得我们在编写套接字级别的协议时,可以更多地尝试使用 TCPClient 、UDPClient和TcpListener,而不是直接向 Socket 中写。
可见,TcpClient类基于Socket类构建,这是它能够以更高的抽象程度提供TCP服务的基础。正因为这样,许多应用程上的通讯协议,比如FTP(File Transfers Protocol)文件传输协议、HTTP超文本传输协议等都直接创建在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类的三种构造函数之一:
1、public TcpClient()当使用这种不带任何参数的构造函数时,将使用本机默认的ip地址并将使用默认的通信端口号0。这样情况下,如果本机不止一个ip地址,将无法选择使用。以下语句示例了如何使用默认构造函数来创建新的 TcpClient:
TcpClient tcpClientC = new TcpClient();
2、public TcpClient(IPEndPoint)使用本机IPEndPoint创建TcpClient的实例对象。IPEndPoint将网络端点表示为IP地址和端口号,在这里它用于指定在建立远程主机连接时所使用的本地网络接口(IP 地址)和端口号,这个构造方法为使用本机IPAddress和Port提供了选择余地。下面的语句示例了如何使用本地终结点创建 TcpClient 类的实例:
IPHostEntry ipInfo=Dns.GetHostByName("www.tuha.net");//主机信息
IPAddressList[] ipList=ipInfo.AddressList;//IP地址数组
IPAddress ip=ipList[];//多IP地址时一般用第一个
IPEndPoint ipEP=new IPEndPoint(ip,);//得到网络终结点
try{
TcpClient tcpClientA = new TcpClient(ipLocalEndPoint);
}
catch (Exception e ) {
Console.WriteLine(e.ToString());
}
到这里,你可能会感到困惑,客户端要和服务端创建连接,所指定的IP地址及通信端口号应该是远程服务器的呀!事实上的确如此,使用以上两种构造函数,你所实现的只是TcpClient实例对象与IP地址和Port端口的绑定,要完成连接,你还需要显式指定与远程主机的连接,这可以通过TcpClient类的Connect方法来实现,Connet方法使用指定的主机名和端口号将客户端连接到远程主机:
public void Connect(IPEndPoint); 使用指定的远程网络终结点将客户端连接到远程 TCP 主机。
public void Connect(IPAddress, int); 使用指定的 IP 地址和端口号将客户端连接到 TCP 主机。
public void Connect(string, int); 将客户端连接到指定主机上的指定端口。
需要指出的是,Connect方法的所有重载形式中的参数IPEndPoint网络终结点、IPAddress以及表现为string的Dns主机名和int指出的Port端口均指的是远程服务器。
以下示例语句使用主机默认IP和Port端口号0与远程主机建立连接:
TcpClient tcpClient = new TcpClient();//创建TcpClient对象实例
try{
tcpClient.Connect("www.contoso.com",);//建立连接
}
catch (Exception e ){
Console.WriteLine(e.ToString());
}
3、public TcpClient(string, int);初始化 TcpClient 类的新实例并连接到指定主机上的指定端口。与前两个构造函数不一样,这个构造函数将自动建立连接,你不再需要额外调用Connect方法,其中string类型的参数表示远程主机的Dns名,如:www.tuha.net。
以下示例语句调用这一方法实现与指定主机名和端口号的主机相连:
try{
TcpClient tcpClientB = new TcpClient("www.tuha.net", );
}
catch (Exception e ) {
Console.WriteLine(e.ToString());
}
前面我们说,TcpClient类创建在Socket之上,在Tcp服务方面提供了更高层次的抽象,体现在网络数据的发送和接受方面,是TcpClient使用标准的Stream流处理技术,使得它读写数据更加方便直观,同时,.Net框架负责提供更丰富的结构来处理流,贯穿于整个.Net框架中的流具有更广泛的兼容性,构建在更一般化的流操作上的通用方法使我们不再需要困惑于文件的实际内容(HTML、XML 或其他任何内容),应用程序都将使用一致的方法(Stream.Write、Stream.Read) 发送和接收数据。另外,流在数据从 Internet 下载的过程中提供对数据的即时访问,可以在部分数据到达时立即开始处理,而不需要等待应用程序下载完整个数据集。.Net中通过NetworkStream类实现了这些处理技术。
NetworkStream类包含在.NET框架的System.Net.Socket命名空间里,该类专门提供用于网络访问的基础数据流。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",);//建立与远程主机的连接
}
catch(Exception e){
MessageBox.show("连接错误:" +e.Message);
}
try{
NetworkStream stream=new NetworkStream(s,FileAccess.ReadWrite,false);//取得网络传输流
}
2、2、通过TcpClient.GetStream方法:public NetworkStream GetStream();它返回用于发送和接收数据的基础网络流NetworkStream。GetStream 通过将基础 Socket 用作它的构造函数参数来创建 NetworkStream 类的实例。使用前你需要先创TcpClient对象实例并建立与远程主机的连接,示例如下:
TcpClient tcpClient = new TcpClient();//创建TcpClient对象实例
Try{
tcpClient.Connect("www.tuha.net",);//尝试与远程主机相连
}
catch(Exception e){
MessageBox.Show("连接错误:"+e.Message);
}
try{
NetworkStream stream=tcpClient.GetStream();//获取网络传输流
}
catch(Exception e)
{
MessageBox.Show("TcpClient错误:"+e.Message);
}
通过以上方法得到NetworkStream网络流之后,你就可以使用标准流读写方法Write和Read来发送和接受数据了。
以上是.Net下使用TcpClient类实现客户端编程的技术资料,为了向客户端提供这些服务,我们还需要编制相应的服务端程序,前一篇有关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[];//IP
try{
TcpListener tcpListener = new TcpListener(ipAddress, );//创建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();// 创建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, , 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!=)
{
buffer+=received;
buffer+="rn";
//received="";
received=sr.ReadLine();
}
listBox1.Items.Add(buffer);//显示
//关闭
sr.Close();
netStream.Close();
tcpClient.Close();
}
}
参考:http://blog.sina.com.cn/s/blog_7315615d0101wvom.html
TCPClient、TCPListener的用法的更多相关文章
- C# TcpClient TcpListener 简单练习01
下面是读<Visual C#.Net 网络编程>整理的练习代码. 客户端发送命令给服务端,从服务器端获取所有人员的成绩或者指定人员的成绩. 命令格式为 GET 0|1 [Name].0为获 ...
- C#编程 socket编程之TcpClient,TcpListener,UdpClient
应用程序可以通过 TCPClient.TCPListener 和 UDPClient 类使用传输控制协议 (TCP) 和用户数据文报协议 (UDP) 服务.这些协议类建立在 System.Net.So ...
- NetworkStream的使用(TcpClient,TcpListener)
1.在tcp连接中,Networkstream可以重复读取,重复写入,不用关掉连接. 2.关掉NetworkStream会自动关闭掉Tcp连接 3.NetworkStream不需要使用Flush方法, ...
- [C#]使用TcpListener及TcpClient开发一个简单的Chat工具
本文为原创文章.源代码为原创代码,如转载/复制,请在网页/代码处明显位置标明原文名称.作者及网址,谢谢! 本文使用的开发环境是VS2017及dotNet4.0,写此随笔的目的是给自己及新开发人员作为参 ...
- winform网络编程之TcpClient类,TcpListener类和UdpClient类
TcpClient类和TcpListener类 (1)TcpClient的用途: 用于在同步阻止模式下通过网络来链接.发送和接受流数据,在此情况下,必须有侦听此连接的请求,而侦听的任务就交给TcpLi ...
- C#-关于TcpListener的AcceptTcpClient()方法造成线程阻塞,进而程序无法彻底关闭的问题
https://blog.csdn.net/nuistchn/article/details/50809158 在<C#高级编程>第7版第24章,有提到使用TCP类. 书中写了一个实例,两 ...
- TCP同步传送数据示例(简洁、清楚)
转自:http://www.2cto.com/kf/201206/134841.html 本例子写了个简单的TCP数据传送功能.没有使用BinaryWriter,BinaryReader,而是使用Ne ...
- TCP同步传送数据示例以及可能出现问题分析
TCP传送数据可以分为同步传送和异步传送,首先这里使用了TCP的同步传送方式,学习了TCP同步传送数据的原理. 同步工作方式是指利用TCP编写的程序执行到监听或者接受数据语句的时候,在未完成当前工作( ...
- C#网络程序设计(3)网络传输编程之TCP编程
网络传输编程指基于各种网络协议进行编程,包括TCP编程,UDP编程,P2P编程.本节介绍TCP编程. (1)TCP简介: TCP是TCP/IP体系中最重要的传输层协议,它提供全双工和可 ...
随机推荐
- [bzoj2962]序列操作_线段树_区间卷积
序列操作 bzoj-2962 题目大意:给定一个n个数的正整数序列,m次操作.支持:1.区间加:2.区间取相反数:3.区间求选c个数的乘积和. 注释:$1\le n,m\le 5\cdot 10^4$ ...
- Strongly connected-HDU4635
Problem - 4635 http://acm.hdu.edu.cn/showproblem.php?pid=4635 题目大意: n个点,m条边,求最多再加几条边,然后这个图不是强连通 分析: ...
- 创建简单的spring-mvc项目
1.第一步:创建项目 new—>Dynamic Web Project 项目创建成功后,展示如图: 2.第二步:导入springmvc的jar包和common-logging.jar 3.第三步 ...
- IDUtil 永不重复的ID
package com.xxx.common.util; import java.util.Random; /** * 各种id生成策略 * * @version 1.0 */ public clas ...
- Use Elasticksearch to solve TOP N issue
The raw data is like timestamp, router, interface, src_ip, dst_ip, protocol, pkts 10000000, 1.1.1.1 ...
- ecstore
- no matching function transform?
http://stackoverflow.com/questions/19876746/stdtolower-and-visual-studio-2013 http://forums.codeguru ...
- #!/usr/bin/env 脚本解释程序的作用
the Zimbu programming language http://www.zimbu.org/getting-started -------------------------------- ...
- Jenkins 使用
Jenkins 安装 Jenkins是用Java语言开发的系统,首先要确定服务器上已经安装JDK或者JRE. 安装方式一 直接运行java –jar Jenkins.war,在浏览器中输入 http: ...
- Photoshop制作的ico图标方法
photoshop是打不开ico的.只是能够通过安装插件实现. 插件点击这里能够下载. 用法,解压后的插件文件 粘贴到: (英文版路径) /program files/adobe/photoshop ...