网络通讯,基于TCP协议,C#,实现

news/2024/5/17 19:51:56 标签: tcp, 通讯, 网络, c#, 服务器, byte

用C#实现基于TCP协议的网络通讯 


      TCP协议是一个基本的网络协议,基本上所有的网络服务都是基于TCP协议的,如HTTP,FTP
等等,所以要了解网络编程就必须了解基于TCP协议的编程。然而TCP协议是一个庞杂的体系,要
彻底的弄清楚它的实现不是一天两天的功夫,所幸的是在.net framework环境下,我们不必要去
追究TCP协议底层的实现,一样可以很方便的编写出基于TCP协议进行网络通讯的程序。 
   
  要进行基于TCP协议的网络通讯,首先必须建立同远程主机的连接,连接地址通常包括两
部分——主机名和端口,如www.yesky.com:80中,www.yesky.com就是主机名,80指主机的80端
口,当然,主机名也可以用IP地址代替。当连接建立之后,就可以使用这个连接去发送和接收数
据包,TCP协议的作用就是保证这些数据包能到达终点并且能按照正确的顺序组装起来。 
   
  在.net framework的类库(Class Library)中,提供了两个用于TCP网络通讯的类,分别
是TcpClient和TcpListener。由其英文意义显而易见,TcpClient类是基于TCP协议的客户端类,
而TcpListener是服务器端,监听(Listen)客户端传来的连接请求。TcpClient类通过TCP协议与
服务器进行通讯并获取信息,它的内部封装了一个Socket类的实例,这个Socket对象被用来使用
TCP协议向服务器请求和获取数据。因为与远程主机的交互是以数据流的形式出现的,所以传输
的数据可以使用.net framework中流处理技术读写。在我们下边的例子中,你可以看到使用
NetworkStream类操作数据流的方法。 
   
  在下面的例子中,我们将建立一个时间服务器,包括服务器端程序和客户端程序。服务器
端监听客户端的连接请求,建立连接以后向客户端发送当前的系统时间。 
   
  先运行服务器端程序,下面截图显示了服务器端程序运行的状况: 
   
   
   
  然后运行客户端程序,客户端首先发送连接请求到服务器端,服务器端回应后发送当前时
间到客户端,这是客户端程序的截图: 
   
   
   
  发送完成后,服务器端继续等待下一次连接: 
   
   
   
  通过这个例子我们可以了解TcpClient类的基本用法,要使用这个类,必须使用
System.Net.Socket命名空间,本例用到的三个命名空间如下: 
   
  using System; 
  using System.Net.Sockets; 
  using System.Text;//从字节数组中获取字符串时使用该命名空间中的类 
   
  首先讨论一下客户端程序,开始我们必须初始化一个TcpClient类的实例: 
   
  TcpClient client = new TcpClient(hostName, portNum); 
   
  然后使用TcpClient类的GetStream()方法获取数据流,并且用它初始化一个
NetworkStream类的实例: 
   
  NetworkStream ns = client.GetStream(); 
   
  注意,当使用主机名和端口号初始化TcpClient类的实例时,直到跟服务器建立了连接,
这个实例才算真正建立,程序才能往下执行。如果因为网络不通,服务器不存在,服务器端口未
开放等等原因而不能连接,程序将抛出异常并且中断执行。 
   
  建立数据流之后,我们可以使用NetworkStream类的Read()方法从流中读取数据,使用
Write()方法向流中写入数据。读取数据时,首先应该建立一个缓冲区,具体的说,就是建立一
byte型的数组用来存放从流中读取的数据。Read()方法的原型描述如下: 
   
  public override int Read(in byte[] buffer,int offset,int size) 
   
  buffer是缓冲数组,offset是数据(字节流)在缓冲数组中存放的开始位置,size是读取
的字节数目,返回值是读取的字上海管道疏通节数。在本例中,简单地使用该方法来读取服务器
反馈的信息: 
   
  byte[] bytes = new byte[1024];//建立缓冲区 
  int bytesRead = ns.Read(bytes, 0, bytes.Length);//读取字节流 
   
  然后显示到屏幕上: 
   
  Console.WriteLine(Encoding.ASCII.GetString(bytes,0,bytesRead)); 
   
  最后不要忘记关闭连接: 
   
  client.Close(); 
   
  下面是本例完整的程序清单: 
   
  using System; 
  using System.Net.Sockets; 
  using System.Text; 
   
  namespace TcpClientExample 
  { 
  public class TcpTimeClient 
  { 
  private const int portNum = 13;//服务器端口,可以随意修改 
  private const string hostName = "127.0.0.1";//服务器地址,127.0.0.1指
本机 
   
  [STAThread] 
  static void Main(string[] args) 
  { 
  try 
  { 
  Console.Write("Try to connect to 
"+hostName+":"+portNum.ToString()+"/r/n"); 
  TcpClient client = new TcpClient(hostName, portNum); 
  NetworkStream ns = client.GetStream(); 
  byte[] bytes = new byte[1024]; 
  int bytesRead = ns.Read(bytes, 0, bytes.Length); 
   
  Console.WriteLine(Encoding.ASCII.GetString
(bytes,0,bytesRead)); 
   
  client.Close(); 
  Console.ReadLine();//由于是控制台程序,故为了清楚的看到结果,
可以加上这句 
   
  } 
  catch (Exception e) 
  { 
  Console.WriteLine(e.ToString()); 
  } 
  } 
  } 
  } 
   
  上面这个例子清晰地演示了管道疏通客户端程序的编写要点,下面我们讨论一下如何建立
服务器程序。这个例子将使用TcpListener类,在13号端口监听,一旦有客户端连接,将立即向
客户端发送当前服务器的时间信息。 
   
  TcpListener的关键在于AcceptTcpClient()方法,该方法将检测端口是否有未处理的连接
请求,如果有未处理减速机的连接请求,该方法减速器将使服务器同客户端建立连接,并且返回
一个TcpClient对象,通过这个对象的减速电机GetStream方法建立同客户端通讯的数据流。事实
上,TcpListener类还提供一个更为灵活的方法除湿机AcceptSocket(),当然灵活的代价是复杂
,对于比较简单的程序,AcceptTcpClient()已经足够用了。此外,TcpListener类提供Start()
方法开始监听,提供Stop()方法停止监听。 
   
  首先我们使用端口初始化一个TcpListener实例,并且开始在13端口监听: 
   
  private const int portNum = 13; 
  TcpListener listener = new TcpListener(portNum); 
  listener.Start();//开始监听 
   
  如果有未处理的连接请求,使用AcceptTcpClient方法进行处理,并且获取数据流: 
   
  TcpClient client = listener.AcceptTcpClient(); 
  NetworkStream ns = client.GetStream(); 
   
  然后,获取本机时间,并保存在字节数组中,使用NetworkStream.Write()方法写入数据
流,然后客户端就可以通过Read()传奇世界私服方法从数据流中获取这段信息: 
   
  byte[] byteTime = Encoding.ASCII.GetBytes(DateTime.Now.ToString()); 
  ns.Write(byteTime, 0, byteTime.Length); 
  ns.Close();//不要忘记关闭数据流和连接 
  client.Close(); 
   
  服务器端程序完整的程序清单如下: 
   
  using System; 
  using System.Net.Sockets; 
  using System.Text; 
   
   
  namespace TimeServer 
  { 
  class TimeServer 
  { 
  private const int portNum = 13; 
   
  [STAThread] 
  static void Main(string[] args) 
  { 
  bool done = false; 
  TcpListener listener = new TcpListener(portNum); 
  listener.Start(); 
  while (!done) 
  { 
  Console.Write("Waiting for connection..."); 
  TcpClient client = listener.AcceptTcpClient(); 
   
  Console.WriteLine("Connection accepted."); 
  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) 
  { 
  Console.WriteLine(e.ToString()); 
  } 
  } 
   
  listener.Stop(); 
  } 
  } 
  } 
   
  把上面两段程序分别编译运行,OK,我们已经用C#实现了基于TCP协议的网络通讯,怎么
样?很简单吧!  


http://www.niftyadmin.cn/n/1415273.html

相关文章

Spring中AOP相关概念

Join point(连接点) 所谓连接点是指那些被拦截到的点。在 Spring中这些点指的是方法,可以看作正在访问的,或者等待访问的那些需要被增强功能的方法。Spring 只支持方法类型的连接点。 Pointcut(切入点) …

tyvj 1666 城市建设【最小生成树】

-Wall是个好东西,要不然我至死都看不出来我把(b[i]b[j])写成了(b[i],b[j])…… 还是来自lyd的题解: (其实原来课件第一行式子写错了没有-1,然而我用sai手画了一个上去hhhh,板绘选手表示鼠绘真难) #include&…

看看你的操作系统几岁了,非常好的DOS指令

Windows系统安装使用到现在,想知道它的“高龄”是多少吗?以Windows XP系统来说,按“WINR”快捷键,输入“CMD”回车后,再在DOS窗口下输入“systeminfo”命令,就可以查看到您的Windows XP出生日期了(指Windo…

Hamming Weight的算法分析

Hamming Weight的算法分析 看代码时遇到一个求32bit二进制数中1的个数的问题,感觉算法很奇妙,特记录学习心得于此,备忘。 计算一个64bit二进制数中1的个数。 解决这个问题的算法不难,很自然就可以想到,但是要给出问题的…

Spring中execution语法

语法格式 execution(修饰符 返回类型 切入点类 切入点方法(参数) 异常抛出)修饰符: 可选,支持通配符,(public/private/protected) 返回类型: 必填,支持通配符,可以使用 * 来匹配所有的返回值类…

使用 nghttpx 搭建 HTTP/2 代理 (转)

来自http://www.fanyue.info/2015/08/nghttpx-http2.html 使用 nghttpx 搭建 HTTP/2 代理 [转] HTTP/1.1,定义于 1999 年,至今仍在流行。纵使人们试图在它上面添加各种黑科技,但它依然有各种各样的不足。终于,在 2015 年 5 月&…

Ubuntu 14.10安装libvirt KVM

2019独角兽企业重金招聘Python工程师标准>>> 默认apt缘是ubuntu官方,修改为国内较快的,如阿里云、网易、搜狐等 wqswqs-Rev-1-0:~$ cd /etc/apt wqswqs-Rev-1-0:/etc/apt$ sudo cp sources.list sources.list_ori wqswqs-Rev-1-0:/etc/apt$ s…

Spring中使用AOP的几种方式

在Spring中使用AOP进行切面编程主要有以下几种方式: XML配置XML注解纯注解 XML配置 新建实体类XmlAopBean及切片类XmlAopService 实体类XmlAopBean package XmlAopBean;import java.text.MessageFormat;public class XmlAopBean {public void runWithoutArgs()…