异步Socket通信

原创 2002年09月25日 10:33:00

异步Socket通信
By John McTainsh  
From:
http://www.codeproject.com/csharp/socketsincs.asp
Translate by: Hillfree


本文介绍如何使用非阻塞方式的Socket通信,并且创建了一个聊天程序的例子来帮助说明。

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

介绍

本文介绍如何在多个应用程序之间创建和使用TCP/IP Socket来进行通信。这些应用程序可以运行在同一台机器,也可以在局域网内,甚至也可以是跨越Internet*。这种方法的好处是不需要你自己来使用线程,而是通过调用Socket的非阻塞模式来实现。在例子中:服务器创建病侦听客户端的连接,一旦有客户连接,服务器就将其加入到一个活动客户的列表中,某个客户端发送的消息也有服务器发送到各个连接的客户端,就好像聊天室中的那样。或许Remoting (远程调用)是做这种工作更好的办法,但是我们这里还是来学习学习如何使用Socket来实现。

*注意:跨越Internet的通讯要求服务器有独立的IP地址并且不在代理或是放火墙之后。

事件时序

服务器必须要先侦听,客户端才能够连接。下面的图例说明了在一个异步Socket会话中的事件时序。

运行示例

实例代码分为两部分:ChatServer ChatClient. 我们首先来创建ChatServer ,然后使用下面的Telnet命令来测试它。


这时,服务器上应该出现一条消息来表明这个客户连接的地址和端口。在任一个telnet窗口中键入的字符都会回显到所有与服务器连接的telnet的窗口中。试试从多台机器上并发连接服务器。不要使用localhost或者127.0.0.1来作为服务器程序唯一的侦听地址。

然后运行ChatClient实例作相同的试验和多个客户端和多个telnet并存的测试。

为什么要使用.NETSocket?

.NET在很多地方都用到了sockets,比如:WebServicesRemoting。但是在那些应用中底层的Socket支持已经做好了,不需要直接使用。但是,和其他非.NET系统的Socket打交道或简单通信的场合中Socket的使用还是很有必要的。它可以用来和诸如DOSWindowsUNIX系统进行通信。底层的Socket应用也可以让你减少了诸如组测,权限,域(domains),用户ID,密码等这些麻烦的安全方面的顾虑。

ChatServer / Listener

服务器侦听端口,当有连接请求时,接受该连接并返回一条欢迎信息。在例子中客户连接被加到一个活动客户列表m_aryClients中去。这个列表会根据客户加入和离开作相应的增删。在某些情况下可能会丢失连接,所以在实际的系统中还应该有轮询侦测客户端是否在线的部分。当服务器端的listener收到客户端发来的信息后,它会把消息广播到所有连接的客户端。

下面讨论两种侦听的方法,一个是用轮询(polling),另外一个在使用事件来侦测连接的请求。

方法1 – 使用轮询的 TcpListener

System.Net.Sockets中的TcpListener 类为我们提供了一个侦听和处理客户连接的简单手段。下面的代码侦听连接,接受连接,并且向客户连接发回一个带有时间戳的欢迎信息。如果有另外一个连接请求到来,原来的连接将会丢失。注意,欢迎信息是采用ASCII编码,而不是UNICODE

 

方法2 – 使用带事件的Socket

一个更为优雅的方法是创建一个事件来捕捉连接请求。ChatServer实例就采用了这种方法。首先服务器的名字和地址用下面的代码取得。

 


得到地址之后,我们要把listener这个Socket绑定到这个地址。我们这里使用的侦听端口是399。此外,从位于"C:/WinNT/System32/drivers/etc/Services"的服务文件中读取端口号应该是一个很好的练习。下面的代码绑定Listener并且开始侦听。一个事件handler把所有的连接请求都指向了OnConnectRequest。这样程序就可以不需要等待或者轮询来处理客户连接了。

 


当客户连接请求到达时,就会激发下面的处理事件。下面的代码首先创建了client Socket),然后发回欢迎信息,接着重新建立了接受事件处理(accept event handler)

 

 

这段代码可以扩展,维护客户Socket的列表,监控数据接收和连接断开。对于连接断开的侦测放在AsyncCallback 事件处理中。ChatClient部分将在下面细述该机制。

ChatClient

ChatClient是一个Windows Form应用程序,用来连接服务器,收发消息。

连接

当点击界面上的连接按钮使执行下面的程序使客户连接到服务器。

 

 

 

如果连接已经存在就销毁它。创建一个Socket和指定的端点相连。 被注释掉部分的代码采用简单的阻塞式连接方法。BeginConnect 则用来做一个非阻塞的连接请求。注意,即使是一个非阻塞的用户连接请求,连接也回被阻塞知道机器名称被解析为IP地址。所以,要尽量使用IP地址而不是机器名来避免这种情况。一旦连接请求处理完毕就会调用下面的方法,它显示连接错误或者在成功连接的情况下建立起接收数据的回调。

 

 

接收数据 

为了异步接收数据,有必要建立一个AsyncCallback 来处理被诸如接到数据和连接断开所激发的事件。用下面的方法。

SetupRecieveCallback 方法启动了BeginReceive ,并利用代理指针把回调指向OnReceveData 方法。同时它也把一个用来接收数据的缓冲传递过去。

 

 

 

当上面的事件被激发时,接收到的数据被默认为是ASCII编码的。新数据也会被激发的事件显示出来。尽管可以调用Add() 在列表中显示新数据,但这并不是一个好主意,因为收到的数据很有可能要被送到其他线程中去处理。注意,需要在接收之后重建接收回调,来确保可以继续接收数据。因为有可能数据很多,超过最初的buffer容量。

创建 AddMessage 委托可以降低Socket线程和用户界面线程的耦合程度,如下所示:

 

 

使用UNICODE

当时用比特流来发送接收数据时,数据就需要被适当的编码。C# 采用多字节字符编码,尽管这里使用Encoding.ASCII ,但如果需要也可以使用Encoding.UNICODE

不要相信发出什么就能收到什么

当接收数据事件被激发,接收的数据被放置到接收缓冲中去。在我们的开发中,分组发送往往对应一个分组接收事件。但是在真正的系统中并非如此。数据并不是都是规规矩矩的在报文中,而有可能被拆分到若干个分组中。不要指望总能收到完整的报文,也不要指望建立自己的符号标记报文的开始和结束就万事大吉了。

结论

尽管使用Socket并不难,但是要用的很好还是需要大量的实践练习。当然在合适的场合你也应该试试使用WebServicesRemoting。此外,Wrox出版社的Professional ADO.NET Programming这本书很不错,值得一看。

C#中Socket通信编程的异步实现

本文将在C#中Socket同步通信的基础上,分析和研究Socket异步编程的实现方法,目的是深入了解Socket编程的基本原理,增强对网络游戏开发相关内容的认识。 什么是Socket编程的异步是实现 ...
  • mss359681091
  • mss359681091
  • 2016年06月30日 15:49
  • 15519

C#中Socket通信编程的异步实现

本文将在C#中Socket同步通信的基础上,分析和研究Socket异步编程的实现方法,目的是深入了解Socket编程的基本原理,增强对网络游戏开发相关内容的认识。什么是Socket编程的异步是实现所谓...
  • qinyuanpei
  • qinyuanpei
  • 2015年03月23日 21:36
  • 5850

C# Socket编程 同步以及异步通信

套接字简介:套接字最早是Unix的,window是借鉴过来的。TCP/IP协议族提供三种套接字:流式、数据报式、原始套接字。其中原始套接字允许对底层协议直接访问,一般用于检验新协议或者新设备问题,很少...
  • luckypeng
  • luckypeng
  • 2014年05月13日 14:40
  • 2288

C++下的socket异步通信源代码

  • 2011年03月31日 20:18
  • 12KB
  • 下载

纯Socket编写的client和server端2个程序,多线程文件异步上传,通信

  • 2017年12月05日 14:45
  • 67KB
  • 下载

C# Socket 同步和异步通信

  • 2017年11月28日 13:39
  • 343KB
  • 下载

Socket 异步通信

  • 2013年12月09日 13:28
  • 79KB
  • 下载

Socket异步通信,线程,双端队列

  • 2010年05月21日 11:45
  • 247KB
  • 下载

关于socket的基于TCP协议的异步通信系统--TongXing.DLL

  • 2014年04月21日 22:34
  • 145KB
  • 下载

VC++异步通信的socket类

  • 2008年07月07日 13:58
  • 97KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:异步Socket通信
举报原因:
原因补充:

(最多只允许输入30个字)