socket客户端在接受/发送的同时,如何接受服务端发过来的“其他通知消息”??

Fred_Mark 2008-11-18 02:47:38
socket客户端采用MSDN上的异步阻塞的方式接受/发送数据,如下:

Socket socket = ...;
ManualResetEvent connectDone = new ManualResetEvent(false);
ManualResetEvent sendDone = new ManualResetEvent(false);
...............

socket.beginSend(.....);
sendDone.WaitOne();
socket.beginRecevie(.....);
receiveOne.WaitOne();
..................
socket.beginSend(.....);
sendDone.WaitOne();
socket.beginRecevie(.....);
receiveOne.WaitOne();
..................
(还有许多...)

基本上都是先send一个数据到服务端,然后receive一个服务端发过来数据(简单点,叫“应答消息”吧)。
同时,客户端还需要接受服务端发过来的“其他通知消息”,这些消息是服务端从发过来的通知,发送时机在服务端的发送序列中。
服务端程序c/c++编写在linux服务器下运行,协议已经定义好,协议/程序都可以更改。

根据协议,读取解析包头就能知道那些消息是“其他通知消息”而非“应答消息”
那么,怎么样接受这些消息呢?

设想如下:
1、写一个reveivePeek方法,使用SocketFlags.Peek参数,然后再主程序中开一个线程,循环检查包头?---这样做会不会读到垃圾数据?如果主程序在正常的发送/接受的情况下?
2、把这些“其他通知消息”作为带外消息接受?使用SocketFlags.OutOfBand参数?这样可以吗?带外数据长度可以为多少?
3、或者其他的????

小弟初学socket,可能描述的不清楚,请各位高手指点,谢谢!!
...全文
330 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
dreamsnake 2008-11-19
  • 打赏
  • 举报
回复
不是很精通,不过,我觉得按照这个思路的话,似乎发送的时候,不要读取好了,所有的读取,全部用一个线程来做,读取的线程用来解析接收到内容,并分别处理。
而发送的线程,如果根据应答消息来决定下一步操作的话,可以将所有发送线程的sendDone实例放入一个集合中,接收的线程应该能够根据接收到的应答,知道是哪个线程的操作(比方每个线程开始发送的时候,先发送一个编号,应答信息中包含这个编号来进行应答),这样,接收线程就可以找到对应的sendDone实例,解除阻塞,或告知发送线程服务器的响应状态了。

我记得曾经写过一个类似的小东东,思路就是上面这个思路吧。呵呵
Fred_Mark 2008-11-18
  • 打赏
  • 举报
回复
楼上的同学,你可能还没理解我的意思。

很简单,假如我们开了一个检查的peek线程,如果服务端没有“其他消息”过来,客户端发送getdate()函数过去,返回一个10000个byte的buffer。
我们检查peek线程了一下前面12个byte的同时,主进程在异步读取了2048个byte,那么peek线程还会继续检查10000-2048=7xxx个buffer开始的12位?这样不是会读到脏数据?

还请认真看题再回答,希望能给出详细的分析,谢谢!
mjjzg 2008-11-18
  • 打赏
  • 举报
回复
其他通知消息??
可以用特殊的标记标明,当客户端接收到的时候给个判断就可以了
Fred_Mark 2008-11-18
  • 打赏
  • 举报
回复
getdate(),setdata()都是类似的函数名,客户端发消息给服务端,必须得到服务端的相应的。

程序刚开始就是采用同步的方式做的, 因为想接受服务端的数据,才改成异步的。。
Fred_Mark 2008-11-18
  • 打赏
  • 举报
回复
问题是我是发送之后才接受的啊?就是事件驱动的。
好像这么说吧,我执行的顺序如下:
getdate()
------>>
<<------
setdate()
------>>
<<------
getdate()
------>>
<<------
setdate()
------>>
<<------

不发送就不接受的,当然我可以开一个线程专门接受数据。
但如果发送数据一个线程,接受数据一个线程,怎么返回对应的结果?

另外我这样异步发送接受,再开线程有问题吗?或者改成同步的方法?
谢谢!
wzd24 2008-11-18
  • 打赏
  • 举报
回复
你需要专门开一个线程来处理Socket的接收操作。根据不同的包头调用相应的处理程序。
Fred_Mark 2008-11-18
  • 打赏
  • 举报
回复
接受/发送这段代码已经调试过,本问题关键在于如何接受服务端发过来的“其他通知消息“?请各位不要找上面语句语法的错误,谢谢!
Java聊天室程序 需求分析 2.1 业务需求 1. 与聊天室成员一起聊天。 2. 可以与聊天室成员私聊。 3. 可以改变聊天内容风格。 4. 用户注册(含头像)、登录。 5. 服务器监控聊天内容。 6. 服务器过滤非法内容。 7. 服务通知。 8. 服务器踢人。 9. 保存服务器日志。 10.保存用户聊天信息。 2.2 系统功能模块 2.2.1 服务 1.处理用户注册 2.处理用户登录 3.处理用户信息 4.处理用户得到信息 5.处理用户退出 2.2.2 客户 1.用户注册界面及结果 2.用户登录界面及结果 3.用户信息界面及结果 4.用户得到信息界面及结果 5.用户退出界面及结果 2.3 性能需求 运行环境:Windows 9x、2000、xp、2003,Linux 必要环境:JDK 1.5 以上 硬件环境:CPU 400MHz以上,内存64MB以上 3.1.2 客户结构 ChatClient.java 为客户程序启动类,负责客户的启动和退出。 Login.java 为客户程序登录界面,负责用户帐号信息的验证与反馈。 Register.java 为客户程序注册界面,负责用户帐号信息的注册验证与反馈。 ChatRoom.java 为客户程序聊天室主界面,负责接收、聊天内容与服务的Connection.java 亲密合作。 Windowclose 为ChatRoom.java的内部类,负责监听聊天室界面的操作,当用户退出时返回给服务器信息。 Clock.java 为客户程序的一个小程序,实现的一个石英钟功能。 3. 2 系统实现原理 当用户聊天时,将当前用户名、聊天对象、聊天内容、聊天语气和是否私聊进行封装,然后与服务器建立Socket连接,再用对象输出流包装Socket的输出流将聊天信息对象服务 当用户聊天信息时,服务将会收到客户Socket传输过来的聊天信息对象,然后将其强制转换为Chat对象,并将本次用户的聊天信息对象添加到聊天对象集Message中,以供所有聊天用户访问。 接收用户的聊天信息是由多线程技术实现的,因为客户必须时时关注更新服务器上是否有最新消息,在本程序中设定的是3秒刷新服务器一次,如果间隔时间太短将会增加客户服务的通信负担,而间隔时间长就会让人感觉没有时效性,所以经过权衡后认为3秒最佳,因为每个用户都不可能在3秒内连续信息。 当每次用户接收到聊天信息后将会开始分析聊天信息然后将适合自己的信息人性化地显示在聊天信息界面上。 4.1.1 问题陈述 1.接受用户注册信息并保存在一个基于文件的对象型数据库。 2.能够允许注册过的用户登陆聊天界面并可以聊天。 3.能够接受私聊信息并给特定的用户。 4.服务器运行在自定义的口上#1001。 5.服务器监控用户列表和用户聊天信息(私聊除外)。 6.服务器踢人,通知。 7.服务器保存日志。

110,549

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧