欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Visual C#.Net 网络程序开发-Socket篇第1/2页

程序员文章站 2023-10-30 15:31:46
visual c#.net 网络程序开发-socket篇   作者: 宋华  作者: www.aspc...
visual c#.net 网络程序开发-socket篇  
作者: 宋华 

作者: www.aspcool.com 

microsoft.net framework为应用程序访问internet提供了分层的、可扩展的以及受管辖的网络服务,其名字空间system.net和system.net.sockets包含丰富的类可以开发多种网络应用程序。.net类采用的分层结构允许应用程序在不同的控制级别*问网络,开发人员可以根据需要选择针对不同的级别编制程序,这些级别几乎囊括了internet的所有需要--从socket套接字到普通的请求/响应,更重要的是,这种分层是可以扩展的,能够适应internet不断扩展的需要。 

抛开iso/osi模型的7层构架,单从tcp/ip模型上的逻辑层面上看,.net类可以视为包含3个层次:请求/响应层、应用协议层、传输层。webreqeust和webresponse 代表了请求/响应层,支持http、tcp和udp的类组成了应用协议层,而socket类处于传输层。可以如下示意: 


可见,传输层位于这个结构的最底层,当其上面的应用协议层和请求/响应层不能满足应用程序的特殊需要时,就需要使用这一层进行socket套接字编程。 

而在.net中,system.net.sockets 命名空间为需要严密控制网络访问的开发人员提供了 windows sockets (winsock) 接口的托管实现。system.net 命名空间中的所有其他网络访问类都建立在该套接字socket实现之上,如tcpclient、tcplistener 和 udpclient 类封装有关创建到 internet 的 tcp 和 udp 连接的详细信息;networkstream类则提供用于网络访问的基础数据流等,常见的许多internet服务都可以见到socket的踪影,如telnet、http、email、echo等,这些服务尽管通讯协议protocol的定义不同,但是其基础的传输都是采用的socket。 

其实,socket可以象流stream一样被视为一个数据通道,这个通道架设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。 


可见,在应用程序端或者服务器端创建了socket对象之后,就可以使用send/sentto方法将数据发送到连接的socket,或者使用receive/receivefrom方法接收来自连接socket的数据; 

针对socket编程,.net 框架的 socket 类是 winsock32 api 提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法,大多数情况下,socket 类方法只是将数据封送到它们的本机 win32 副本中并处理任何必要的安全检查。如果你熟悉winsock api函数,那么用socket类编写网络程序会非常容易,当然,如果你不曾接触过,也不会太困难,跟随下面的解说,你会发觉使用socket类开发windows 网络应用程序原来有规可寻,它们在大多数情况下遵循大致相同的步骤。 

在使用之前,你需要首先创建socket对象的实例,这可以通过socket类的构造方法来实现: 

public socket(addressfamily addressfamily,sockettype sockettype,protocoltype protocoltype); 


其中,addressfamily 参数指定 socket 使用的寻址方案,sockettype 参数指定 socket 的类型,protocoltype 参数指定 socket 使用的协议。 

下面的示例语句创建一个 socket,它可用于在基于 tcp/ip 的网络(如 internet)上通讯。 

socket s = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp); 


若要使用 udp 而不是 tcp,需要更改协议类型,如下面的示例所示: 

socket s = new socket(addressfamily.internetwork, sockettype.dgram, protocoltype.udp); 


一旦创建 socket,在客户端,你将可以通过connect方法连接到指定的服务器,并通过send/sendto方法向远程服务器发送数据,而后可以通过receive/receivefrom从服务端接收数据;而在服务器端,你需要使用bind方法绑定所指定的接口使socket与一个本地终结点相联,并通过listen方法侦听该接口上的请求,当侦听到用户端的连接时,调用accept完成连接的操作,创建新的socket以处理传入的连接请求。使用完 socket 后,记住使用 shutdown 方法禁用 socket,并使用 close 方法关闭 socket。其间用到的方法/函数有: 

socket.connect方法:建立到远程设备的连接 
public void connect(endpoint remoteep)(有重载方法) 
socket.send 方法:从数据中的指示位置开始将数据发送到连接的 socket。 
public int send(byte[], int, socketflags);(有重载方法) 
socket.sendto 方法 将数据发送到特定终结点。 
public int sendto(byte[], endpoint);(有重载方法) 
socket.receive方法:将数据从连接的 socket 接收到接收缓冲区的特定位置。 
public int receive(byte[],int,socketflags); 
socket.receivefrom方法:接收数据缓冲区中特定位置的数据并存储终结点。 
public int receivefrom(byte[], int, socketflags, ref endpoint); 
socket.bind 方法:使 socket 与一个本地终结点相关联: 
public void bind( endpoint localep ); 
socket.listen方法:将 socket 置于侦听状态。 
public void listen( int backlog ); 
socket.accept方法:创建新的 socket 以处理传入的连接请求。 
public socket accept(); 
socket.shutdown方法:禁用某 socket 上的发送和接收 
public void shutdown( socketshutdown how ); 
socket.close方法:强制 socket 连接关闭 
public void close(); 


可以看出,以上许多方法包含endpoint类型的参数,在internet中,tcp/ip 使用一个网络地址和一个服务端口号来唯一标识设备。网络地址标识网络上的特定设备;端口号标识要连接到的该设备上的特定服务。网络地址和服务端口的组合称为终结点,在 .net 框架中正是由 endpoint 类表示这个终结点,它提供表示网络资源或服务的抽象,用以标志网络地址等信息。.net同时也为每个受支持的地址族定义了 endpoint 的子代;对于 ip 地址族,该类为 ipendpoint。ipendpoint 类包含应用程序连接到主机上的服务所需的主机和端口信息,通过组合服务的主机ip地址和端口号,ipendpoint 类形成到服务的连接点。 

用到ipendpoint类的时候就不可避免地涉及到计算机ip地址,.net中有两种类可以得到ip地址实例: 

ipaddress类:ipaddress 类包含计算机在 ip 网络上的地址。其parse方法可将 ip 地址字符串转换为 ipaddress 实例。下面的语句创建一个 ipaddress 实例: 

ipaddress myip = ipaddress.parse("192.168.1.2"); 


dns 类:向使用 tcp/ip internet 服务的应用程序提供域名服务。其resolve 方法查询 dns 服务器以将用户友好的域名(如"host.contoso.com")映射到数字形式的 internet 地址(如 192.168.1.1)。resolve方法 返回一个 iphostenty 实例,该实例包含所请求名称的地址和别名的列表。大多数情况下,可以使用 addresslist 数组中返回的第一个地址。下面的代码获取一个 ipaddress 实例,该实例包含服务器 host.contoso.com 的 ip 地址。 

iphostentry iphostinfo = dns.resolve("host.contoso.com"); 
ipaddress ipaddress = iphostinfo.addresslist[0]; 


你也可以使用gethostname方法得到iphostentry实例: 

iphosntentry hostinfo=dns.gethostbyname("host.contoso.com") 


在使用以上方法时,你将可能需要处理以下几种异常: 

socketexception异常:访问socket时操作系统发生错误引发 

argumentnullexception异常:参数为空引用引发 

objectdisposedexception异常:socket已经关闭引发 

在掌握上面得知识后,下面的代码将该服务器主机( host.contoso.com的 ip 地址与端口号组合,以便为连接创建远程终结点: 

ipendpoint ipe = new ipendpoint(ipaddress,11000); 

1