已阅读5页,还剩8页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
异步Socket通信By John McTainsh From: /csharp/socketsincs.aspTranslate by: Hillfree本文介绍如何使用非阻塞方式的Socket通信,并且创建了一个聊天程序的例子来帮助说明。所谓同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令。 异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。 并不是说谁好谁不好,只是同步的机制不适合在正式应用的项目当中(但自己测试还是可以的) 2.同步,就是实时处理,比如服务器一接收客户端请求,马上响应,这样客户端可以在最短的时间内得到结果,但是如果多个客户端,或者一个客户端发出的请求很频繁,服务器无法同步处理,就会造成涌塞。 异步,就是分时处理,服务器接收到客户端请求后并不是立即处理,而是等待服务器比较空闲的时候加以处理,可以避免涌塞。3.有同步和异步之分同步就是调用一个函数,直接函数执行完了才返回到调用函数异步就是被调用函数初始化完后马上返回.介绍本文介绍如何在多个应用程序之间创建和使用TCP/IP Socket来进行通信。这些应用程序可以运行在同一台机器,也可以在局域网内,甚至也可以是跨越Internet的*。这种方法的好处是不需要你自己来使用线程,而是通过调用Socket的非阻塞模式来实现。在例子中:服务器创建病侦听客户端的连接,一旦有客户连接,服务器就将其加入到一个活动客户的列表中,某个客户端发送的消息也有服务器发送到各个连接的客户端,就好像聊天室中的那样。或许Remoting (远程调用)是做这种工作更好的办法,但是我们这里还是来学习学习如何使用Socket来实现。 *注意:跨越Internet的通讯要求服务器有独立的IP地址并且不在代理或是放火墙之后。 事件时序 服务器必须要先侦听,客户端才能够连接。下面的图例说明了在一个异步Socket会话中的事件时序。 运行示例 实例代码分为两部分:ChatServer 和ChatClient. 我们首先来创建ChatServer ,然后使用下面的Telnet命令来测试它。 telnet server machine IP address or machine name 399telnet 10.328.32.76 399这时,服务器上应该出现一条消息来表明这个客户连接的地址和端口。在任一个telnet窗口中键入的字符都会回显到所有与服务器连接的telnet的窗口中。试试从多台机器上并发连接服务器。不要使用localhost或者来作为服务器程序唯一的侦听地址。 然后运行ChatClient实例作相同的试验和多个客户端和多个telnet并存的测试。 为什么要使用.NET的Socket? .NET在很多地方都用到了sockets,比如:WebServices和Remoting。但是在那些应用中底层的Socket支持已经做好了,不需要直接使用。但是,和其他非.NET系统的Socket打交道或简单通信的场合中Socket的使用还是很有必要的。它可以用来和诸如DOS,Windows和UNIX系统进行通信。底层的Socket应用也可以让你减少了诸如组测,权限,域(domains),用户ID,密码等这些麻烦的安全方面的顾虑。 ChatServer / Listener 服务器侦听端口,当有连接请求时,接受该连接并返回一条欢迎信息。在例子中客户连接被加到一个活动客户列表m_aryClients中去。这个列表会根据客户加入和离开作相应的增删。在某些情况下可能会丢失连接,所以在实际的系统中还应该有轮询侦测客户端是否在线的部分。当服务器端的listener收到客户端发来的信息后,它会把消息广播到所有连接的客户端。 下面讨论两种侦听的方法,一个是用轮询(polling),另外一个在使用事件来侦测连接的请求。 方法1 使用轮询的 TcpListener System.Net.Sockets中的TcpListener 类为我们提供了一个侦听和处理客户连接的简单手段。下面的代码侦听连接,接受连接,并且向客户连接发回一个带有时间戳的欢迎信息。如果有另外一个连接请求到来,原来的连接将会丢失。注意,欢迎信息是采用ASCII编码,而不是UNICODE。 private Socket client = null;const int nPortListen = 399;try TcpListener listener = new TcpListener( nPortListen ); Console.WriteLine( Listening as 0, listener.LocalEndpoint ); listener.Start(); do byte m_byBuff = new byte127; if( listener.Pending() ) client = listener.AcceptSocket(); / Get current date and time. DateTime now = DateTime.Now; string strDateLine = Welcome + now.ToString(G) + nr; / Convert to byte array and send. Byte byteDateLine = System.Text.Encoding.ASCII.GetBytes( strDateLine.ToCharArray() ); client.Send( byteDateLine, byteDateLine.Length, 0 ); else Thread.Sleep( 100 ); while( true ); / Dont use this. catch( Exception ex ) Console.WriteLine ( ex.Message );方法2 使用带事件的Socket 一个更为优雅的方法是创建一个事件来捕捉连接请求。ChatServer实例就采用了这种方法。首先服务器的名字和地址用下面的代码取得。 IPAddress aryLocalAddr = null;string strHostName = ;try / NOTE: DNS lookups are nice and all but quite time consuming. strHostName = Dns.GetHostName(); IPHostEntry ipEntry = Dns.GetHostByName( strHostName ); aryLocalAddr = ipEntry.AddressList;catch( Exception ex ) Console.WriteLine (Error trying to get local address 0 , ex.Message );/ Verify we got an IP address. Tell the user if we didif( aryLocalAddr = null | aryLocalAddr.Length 0 ) / Wrote the data to the List string sRecieved = Encoding.ASCII.GetString( m_byBuff, 0, nBytesRec ); / WARNING : The following line is NOT thread safe. Invoke is / m_lbRecievedData.Items.Add( sRecieved ); Invoke( m_AddMessage, new string sRecieved ); / If the connection is still usable restablish the callback SetupRecieveCallback( sock ); else / If no data was recieved then the connection is probably dead Console.WriteLine( Client 0, disconnected, sock.RemoteEndPoint ); sock.Shutdown( SocketShutdown.Both ); sock.Close(); catch( Exception ex ) MessageBox.Show( this, ex.Message, Unusual error druing Recieve! ); 当上面的事件被激发时,接收到的数据被默认为是ASCII编码的。新数据也会被激发的事件显示出来。尽管可以调用Add() 在列表中显示新数据,但这并不是一个好主意,因为收到的数据很有可能要被送到其他线程中去处理。注意,需要在接收之后重建接收回调,来确保可以继续接收数据。因为有可能数据很多,超过最初的buffer容量。 创建 AddMessage 委托可以降低Socket线程和用户界面线程的耦合程度,如下所示: / Declare the delegate prototype to send data back to the formdelegate void AddMessage( string sNewMessage );namespace ChatClient . . . public class FormMain : System.Windows.Forms.Form private event AddMessage m_AddMessage; / Add Message Event handler for Form . . . public FormMain() . . . / Add Message Event handler for Form decoupling from input thread m_AddMessage = new AddMessage( OnAddMessage ); . . . public void OnAddMessage( string sMessage ) / Thread safe operation here m_lbRecievedData.Items.Add( sMessage ); public void OnSomeOtherThread() . . . string sSomeText = Bilbo Baggins; Invoke( m_AddMessage, new string sSomeText ); . . . 使用UNICODE 当时用比特流来发送接收数据时,数据就需要被适当的编码。C# 采用多字节字符编码,尽管这里使用Encoding.ASCII ,但如果需要也可以使用Encoding.UNICODE 不要相信发出什么就能收到什么 当接收数据事件被激发,接收的数据被放置到接收缓
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025遂川县发展和改革委员会公益性岗位招聘2人笔试考试备考题库及答案解析
- 2025河北雄安容西青禾幼儿园、临泉幼儿园教师见习岗招聘考试笔试模拟试题及答案解析
- 赣州市南康区康企家居有限公司劳务派遣制员工招聘笔试考试参考题库及答案解析
- 普车工考试题及答案
- 2025山东枣庄市立医院第二批急需紧缺人才招聘31人笔试考试参考试题及答案解析
- 2025年湖南湘西自治州第二批大学生乡村医生招聘3人考试笔试参考题库附答案解析
- 三台县县属国有企业2025年度第二批次公开招聘工作人员(20人)考试笔试参考题库附答案解析
- 2025广东云浮新兴县“粤聚英才粤见未来”招聘教育人才8人(苏州大学专场)考试笔试参考题库附答案解析
- 吉水县委信访局2025年面向社会公开招聘1名垦民工作岗考试笔试备考试题及答案解析
- 2025下半年安徽合肥市梅山饭店有限公司社会招聘62人笔试考试参考试题及答案解析
- 中华民族共同体概论教案13第十三讲 先锋队与中华民族独立解放(1919-1949)教案
- TB10752-2018 高速铁路桥涵工程施工质量验收标准
- 平行四边形的判定(27张)-完整课件
- 《健康管理学》教案(郭清主编版)
- (高清版)TDT 1061-2021 自然资源价格评估通则
- 2024年三方协议范本-(附件版)
- 高考小说阅读强化训练:孙犁小说专题(附答案解析)
- 培智五年级上次数学期末考试题
- 岗位综合实训课程标准
- 神鸟的故事作文400字
- 大班歌曲《小树叶》
评论
0/150
提交评论