网络编程
使用C#进行网络编程时,通常都需要用到System.Net命名空间、System.Net.Sockets命名空间和System.Net.Mail命名空间;
1. System.Net命名空间:为当前网络上使用的多种协议提供了简单的编程接口。
- DNS类:DNS是一个静态类,它从Internet域名系统(DNS)检索关于特定主机的信息,在IPHostEntry类的实例中返回来自DNS查询的主机信息。(GetHostName()找到本地系统的主机名,然后再用GetHostByName()找到主机的IP地址)
- IPAddress类:包含计算机在IP网络上的地址,主要用来提供网际协议(IP)地址。
- IPEndPoint类包含应用程序连接到主机上的服务所需要的主机和本地或远程端口信息。主要用来将网络端点表示为IP地址和端口号。
- WebClient类:提供向URL标识的任何本地、Intranet或Internet资源发送数据以及从这些资源接收数据的公共方法。
- WebRequest类:.Net Framework的请求/响应模型的抽象基类,用于访问Internet数据。使用该请求/响应模型的应用程序可以用协议不可知的方式从Internet请求数据。
2. System.Net.Sockets命名空间:
主要提供制作Sockets网络应用程序的相关类,其中Socket类,TcpClient类、TcpListener类和UdpClient类较为常用。在.NET框架下开发时,直接使用System.Net.Sockets名称空间中的Socket类编程较为复杂,而应用层的类TcpClient、TcpListener 和 UdpClient为 Socket 通信提供了更简单、对用户更友好的接口。它们和Socket类之间的这种层次关系如图
(1)Socket类:主要用于管理连接(将应用程序与端口连接起来,端口是一台计算机的数据都通过此连接网络, Socket是基于流套接字协议(TCP协议)/基于数据报套接字协议(UDP协议)最为通用的API。),实现Berkeley通信端套接字接口,同时它还定义了绑定、连接网络端点及传输数据所需的各种方法。
-
- void Bind(IPEndPoint localEP):绑定地址,使Socket与一个本地终节点相关联。
- Void Connect(IPEndPoint ip):建立连接
- Void Listen(int backlog):将Socket置于侦听状态, backlog最多可连接数。
- Int Receive(byte[] buffer):接收数据
- Int Receive (byte[] buffer,ref IPEndPoint ip):从指定地址接收数据
- Int Send(byte[] buffer):发送数据
- Int Send To(byte[] buffer,ref IPEndPoint remoteIP):向指定地址发送数据
- Void Shutdown(SocketShutdown how):关闭套接字,how指定不在允许执行的操作
注:使用accept函数建立新的连接时,并不是使用原来的Socket进行通信,而是返回一个新的Socket套接字进行连接通信。原来的Socket继续进入监听状态,等待他人的连接要求。
(2)TcpClient类:基于Socket类构建,用于在同步阻止模式下通过网络来连接,发送,接收数据。
这是它能够以更高的抽象程度提供TCP服务的基础。体现在网络数据的发送和接受方面,是TcpClient使用NetworkStream网络流处理技术,使得它读写数据更加方便直观。TcpClient类专为客户端设计,它为 TCP 网络服务提供客户端连接。
(3)NetworkStream网络流:可以被视为一个数据通道,架设在数据来源端(客户Client)和接收端(服务Server)之间,通过TcpClient.GetStream方法,返回用于发送和接收数据的网络流NetworkStream。
注:要创建NetworkStream必须提供连接的Socket.默认情况下关闭NetworkStream并不会关闭所提供的Socket.如果要关闭Socket权限,则必须将ownsSocket构造函数参数的值指定为true.而后的数据读取及写入均针对这个通道来进行。不支持对网络流的随机访问。
示例如下:通过以下方法得到NetworkStream网络流之后,就可以使用标准流读写方法Write和Read来发送和接受数据了。
1 TcpClient tcpClient = new TcpClient(); //创建TcpClient对象实例 2 tcpClient.Connect("www.baidu.com",4088); //尝试与远程主机相连 3 NetworkStream stream=tcpClient.GetStream(); //获取网络传输流
- BeginRead():从NetworkStream开始一步读取
- BeginWrite():开始向流异步写入
- Close():关闭NetworkStream
- EndRead():处理异步读取结束
- EndWrite():处理异步写入结束
- Flush():刷新流中的数据
- Read():从流中读取
- ReadByte():从流中读取一个字节,并将流内的位置向前推进一个字节。到达末尾,返回-1。
- Write():将数据写入NetworkStream
- WriteByte():将一个字节写入流内的当前位置,并将流内的位置向前推进一个字节。
Server:获取基础网络Socket
- AcceptSocket/AcceptTcpClient:接受挂起的连接请求
- BeginAcceptSocket/BeginAcceptTcpClient:开始一个异步操作来接受一个传入的连接尝试
- Start:开始侦听传入的连接请求
- Stop:关闭侦听
Client客户端连接侦听器的两种方法:
(1)创建一个TcpClient,并调用3个可用Connect方法之一。
(2)使用远程主机的主机名和端口号创建TcpClient,此构造函数将自动尝试一个连接。
- Client:获取或设置基础Socket
- ReceiveBufferSize:获取或设置接收缓冲区的大小
- SendBufferSize:获取或设置发送缓冲区的大小
- BeginConnect方法:开始一个对远程主机连接的异步请求
- Close:释放TcpClient 实例,不关闭基础连接
- Connect:使用指定的主机名和端口号将客户端连接到TCP主机
- GetStream:返回用于发送和接收数据的NetworkStream
创建连接TCPClient连接方法:
(1)创建一个TcpClient,并调用三个可用的Connect()方法之一。
- void Connect(IPEndPoint):使用指定的远程网络节点将客户端连接到远程TCP主机。
1 IPAddress ipAddress = Dns.Resolve(Dns.GetHostName()).AddressList(0);//获取IP地址 2 IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, 60000);//设置端口 3 TcpClient tcpClientA = new TcpClient(ipLocalEndPoint);//创建客户端
2. void Connect(IPAddress,int):使用指定的IP地址和端口号将客户端连接到TcpClient主机。
3. void Connect(string,int):将客户端连接到指定主机上的指定端口。
1 TcpClient tcpClientB = new TcpClient("www.baidu.com", 8888);//创建客户端
(2) 使用远程主机的主机名和端口号创建TcpClient。
1 TcpClient tcpClient = new TcpClient();//创建TcpClient对象实例 2 tcpClient.Connect("www.baidu.com",8080);//建立连接
注:要发送和接受数据,先使用GetStream()方法来获取一个NetworkStream,再调用NetworkStream的Write()和Read()方法与远程主机之间发送和接收数据。最后使用Close()方法释放与TcpClient()关联的所有资源。
TcpListner:用于阻止同步模式下侦听和接受传入的连接请求。
可使用TcpClient类或Socket类来连接TcpListener,并且可以使用IPEndPoint、本地IP地址及端口号来创建TcpListener实例对象。
.Net中的TcpListener主要作用是监视TCP端口上客户端的请求,通过绑定本机IP地址和相应端口创建TcpListener对象实例,并由Start方法启动侦听;当TcpListener侦听到用户端的连接后,通过AcceptTcpClient方法接受传入的连接请求并创建TcpClient以处理请求,或者通过AcceptSocket方法接受传入的连接请求并创建Socket以处理请求。
(1)创建服务器端:
1 //建立TCP监听器TcpListener对象。 2 TcpListener tl=new TcpListener(端口号); 3 //启动监听器 4 tl.Start(); 5 //用监听器获取连接进来的套接字(Socket) 6 Socket s=myList.AcceptSocket(); 7 //通过Socket的Receive方法获取客户端发送的数据 8 byte [] result=new byte[1024]; 9 int k=s.Receive(result); 10 //通过Socket的Send方法向客户端发送数据 11 byte[] st=System.Text.Encoding.Default.GetBytes(“text”); 12 s.Send(st); 13 //在通讯结束后,需要释放资源结束监听 14 s.Close(); 15 tl.Stop();
Socket建立服务器:初始化监听Socket 接受新的客户端连接 收发数据 关闭连接
1 socketServer = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);//创建Socket 客户端 2 //Socket绑定本地端口监听客户端连接; 3 Socket.Bind(端口号); 4 Socket.Listen(); 5 socket.Receive();//创建连接的客户端的Socket并开启线程接收数据; 6 socket.Send();//发送数据 7 socket.Close();//关闭连接
TcpClient创建客户端:
1 //建立TCP客户端TcpClient对象。 2 TcpClient tcpclnt = new TcpClient(); 3 //连接服务器 4 tcpclnt.Connect(IP地址字符串,端口号); 5 //获得客户端网络传输 流 6 Stream stm =tcpclnt.GetStream(); 7 //通过Stream的Write方法向服务器端发送的数据 8 //通过Stream的Read方法读取服务器段发来的数据 9 //在通讯结束后,需要释放资源,结束和服务器的连接 10 tcpclnt.Close();
TCP与UDP的区别
- TCP是面向连接的服务、UDP是面向无连接服务
- TCP是具有差错控制的,而UDP没有缺乏可靠性
- TCP的传输是有序的,UDP是无序的
- UDP的实时性更好,有简单,快速、占用资源少的优点。
- UDP传输限定在64KB之内,Tcp一旦建立连接,就可以按统一的格式传输大量的数据。
使用UdpClient类实现UDP协议编程
由于UDP协议并不需要进行确定的连接,程序中可以不需要考虑连接和一些异常的捕获工作。在有些对数据安全性要求不是很高的情况下采用UDP协议。
在System.Net.Sockets命名空间下的UdpClient类,提供更直观的易于使用的属性和方法,从而降低UDP编程的难度。使用UdpClient时,连接的客户端需要先发送一个信息给服务器,服务器才能和客户端通讯。
UdpClient类的构造函数有以下几种格式:
1 UdpClient(); 2 UdpClient(int port); 3 UdpClient(IPEndPoint iep); 4 UdpClient(string remoteHost,int port);
利用Socket编写UdpClient
1 Socket udpSocket;//创建Socket 2 udpSocket.Bind(IPAddress,IPEndPoint);//把Socket绑定本地IP和端口号 3 //开启线程接收信息:先保存接到信息的端口号,使用ReceiveFrom发送信息 4 EndPoint point = new IPEndPoint(IPAddress.Any, 0);//用来保存发送方的ip和端口号 5 EndPoint point = (EndPoint)IPEndPoint; 6 //发送信息:使用EndPoint创建发送目标的IP和端口号; 7 //关闭线程和Socket
利用UDPClient编程
1 //建立UDP客户端UdpClient对象。 2 UdpClient uc=new UdpClient(端口号); 3 //连接对方远程主机 4 uc.Connect(对方IP地址,对方远程主机的端口号); 5 //开启线程,通过uc的Receive方法获取远程主机发送来的数据 6 IPEndPoint ip=new IPEndPoint(IPAddress.Any,0); 7 byte[] b=uc.Receive(ref ip); 8 //通过uc的Send方法向远程主机发送数据 9 byte[] st=System.Text.Encoding.Default.GetBytes(“text”); 10 uc.Send(st); 11 //在通讯结束后,需要释放资源 12 uc.Close();