C# Socket通讯,针对同一客户端的二次连接请求的疑问?望高手指点迷津!!

雪狼孤竹 2013-05-23 04:34:45
我先说一下我现在发现的情况,我借助网上的实例编写了一个服务器测试程序。
有一个后台线程,负责监听客户端的连接,如果有请求,就会建立一个连接,同时产生一个前台的接收线程接收数据。
对于一个在服务器端已成功建立连接的客户端,能够实现正常的通讯。在非通讯状态下,客户端意外的断开了连接,没有通知服务器,服务器并不知道该客户端已断开。为了实现连接,客户端会再次向服务器发起连接请求,当服务器端收到连接请求的时候,会提示“客户端强行关闭连接”。客户端再次向服务器发起连接请求,服务器接收,建立连接,并产生接收线程。
问题:
1、socket的侦听,对于已建立连接的同一终端,是否还会接收连接请求?
2、服务器对于已连接的终端,在断连后能否在发起第一个连接请求的时候,关闭过去的连接,建立一个新的连接?

注:我只是想知道该方式可否实现和怎么实现,以及您对此的看法。望高手指点迷津,谢谢!!

附上侦听,接受部分代码
/// <summary>   
/// 监听客户端请求的方法;
/// </summary>
void WatchConnecting()
{
while (true) // 持续不断的监听客户端的连接请求;
{
// 开始监听客户端连接请求,Accept方法会阻断当前的线程;
Socket sokConnection = socketWatch.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字;
// 想列表控件中添加客户端的IP信息;
lbOnline.Items.Add(sokConnection.RemoteEndPoint.ToString());
// 将与客户端连接的 套接字 对象添加到集合中;
dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection);
ShowMsgError("客户端连接成功!"); //显示到指定的控件中 自定方法
Thread thr = new Thread(RecMsg);
thr.IsBackground = true;
thr.Start(sokConnection);
dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr); // 将新建的线程 添加 到线程的集合中去。
}
}


///<summary>
///客户端接收数据的方法;
///</summary>
void RecMsg(object sokConnectionparn)
{
Socket sokClient = sokConnectionparn as Socket;
Boolean b_mark = true;
bRMark = false;
while (b_mark)
{
// 定义一个2M的缓存区;
byte[] arrMsgRec = new byte[1024 * 1024 * 2];
// 将接受到的数据存入到输入 arrMsgRec中;
int length = -1;

try
{
length = sokClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度;
if(length <= 0)
{
continue;
}
}
catch (SocketException se)
{
ShowMsgError("异常:" + se.Message); //“客户端强行关闭连接”的提示的发起位置 // 从 通信套接字 集合中删除被中断连接的通信套接字;
dict.Remove(sokClient.RemoteEndPoint.ToString());
// 从通信线程集合中删除被中断连接的通信线程对象;
dictThread.Remove(sokClient.RemoteEndPoint.ToString());
// 从列表中移除被中断的连接IP
lbOnline.Items.Remove(sokClient.RemoteEndPoint.ToString());
break;
}
catch (Exception e)
{
ShowMsgError("异常:" + e.Message);
// 从 通信套接字 集合中删除被中断连接的通信套接字;
dict.Remove(sokClient.RemoteEndPoint.ToString());
// 从通信线程集合中删除被中断连接的通信线程对象;
dictThread.Remove(sokClient.RemoteEndPoint.ToString());
// 从列表中移除被中断的连接IP
lbOnline.Items.Remove(sokClient.RemoteEndPoint.ToString());
break;
}
string strMsg = System.Text.Encoding.ASCII.GetString(arrMsgRec, 0, length);// 将接受到的字节数据转化成字符串;

ShowMsgReceive(strMsg);//显示到指定的控件中 自定方法
}
}
...全文
405 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
雪狼孤竹 2013-05-25
  • 打赏
  • 举报
回复
我等啊等,我等啊等,……
雪狼孤竹 2013-05-24
  • 打赏
  • 举报
回复
引用 6 楼 Mic_Gary 的回复:
想学,关注,并帮楼主顶
谢谢帮顶!! 单位电脑太悲催,连引用都无法出现。 没办法,上别人电脑看看引用的格式,自己编辑引用,累啊!
雪狼孤竹 2013-05-24
  • 打赏
  • 举报
回复
引用 3 楼 wodegege10 的回复:
1.一个socket连接是包含了服务器IP+PORT + 客户端IP+PORT,对于已经建立的连接,那是会拒绝的 (端口复用的情况没试验过,不知道是什么状况) 2.既然无法连接,那么服务器也就不知道客户端请求连接的情况。所以无法实现, 以上是个人想法。 一般处理方法: 1.客户端发送心跳包到服务器 2.服务器使用一个检测线程用来检查每个连接,在规定时间内,没有收到任何包,则认为该连接无效,关闭之 没有看到你客户端的连接代码,不知道你是否绑定了客户端本地的IP和端口,若是没有的话,那么每次连接系统会自动选择合适的端口与服务器建立连接,所以服务器仅仅靠每个客户端的IP+PORT来管理是不合适的。
谢谢您的回复!我对这部分也确实不是很精通,还在学习中。 我没有对客户端太过研究是由于实际情况是,我的客户端是一个硬件设备。目前,这个硬件设备只有上电或复位的时候,才发一个连接请求。但是每次意外断连后,都得重新上电两次,才能重新和我机器上的服务器建立连接,所以才想问问能否一次来解决,在不考虑服务器发现客户端的连接无效的情况下。 如果一次的方式无法解决,那服务器端就得通过其它方式来关闭连接,并等待连接请求,比如心跳,通讯超时等等。不过这个都和这个帖子的本意无关了,都是后话。 发过贴后,自己也想了想在意外断连后,为什么是接收线程发现的异常,而监控监听线程没有结果。 虽然客户端断开了,但是服务器不知道,当客户端发起连接请求的时候,服务器端认为是该客户端的一条通讯数据,所以是接收线程收到数据,监听线程没有收到(也很疑惑是否认为正确),但是接收线程还没有那么高的权限来处理这条数据,感觉有点像把父亲的工作交给了儿子,儿子处理不了,所以发起异常,并自行关闭该连接。 以上也是个人想法,并没有理论依据。 不知还有高人有自己的想法吗?分享一下啊?
Mic_Gary 2013-05-24
  • 打赏
  • 举报
回复
想学,关注,并帮楼主顶
雪狼孤竹 2013-05-24
  • 打赏
  • 举报
回复
引用 2 楼 dixh1989 的回复:
看了下我以前写的客户端和服务端,正常关闭客户端的时候,会发送个断开连接的数据给服务端,如果强行结束客户端的进程,服务端就会报错。。。应该加个Try吧,然后把连接的线程关了就好。 所以我觉得服务端应该不会不知道客户端已经断开了啊。。。
您可能也是没看太明白,我说的是意外断开连接,并没有给服务器端发送断开请求,说的就是非正常的断连。 比如客户端突然掉电,或网络物理断连等等非正常的情况。
雪狼孤竹 2013-05-24
  • 打赏
  • 举报
回复
引用 1 楼 yyantifa 的回复:
客户端接收数据出现异常,为什么要移除这两个. dict.Remove(sokClient.RemoteEndPoint.ToString()); // 从通信线程集合中删除被中断连接的通信线程对象; dictThread.Remove(sokClient.RemoteEndPoint.ToString()); 监听客户端请求的方法这个应该是服务端. dict.add() dictThread.add() 服务器添加,客户端移除??
您可能没有看明白,我上面的是服务器端代码,对于无效的连接,自然要移除了。保留无效的连接,在通讯的时候会出异常的。
wenbin 2013-05-23
  • 打赏
  • 举报
回复
1.一个socket连接是包含了服务器IP+PORT + 客户端IP+PORT,对于已经建立的连接,那是会拒绝的 (端口复用的情况没试验过,不知道是什么状况) 2.既然无法连接,那么服务器也就不知道客户端请求连接的情况。所以无法实现, 以上是个人想法。 一般处理方法: 1.客户端发送心跳包到服务器 2.服务器使用一个检测线程用来检查每个连接,在规定时间内,没有收到任何包,则认为该连接无效,关闭之 没有看到你客户端的连接代码,不知道你是否绑定了客户端本地的IP和端口,若是没有的话,那么每次连接系统会自动选择合适的端口与服务器建立连接,所以服务器仅仅靠每个客户端的IP+PORT来管理是不合适的。
是_这样吗 2013-05-23
  • 打赏
  • 举报
回复
看了下我以前写的客户端和服务端,正常关闭客户端的时候,会发送个断开连接的数据给服务端,如果强行结束客户端的进程,服务端就会报错。。。应该加个Try吧,然后把连接的线程关了就好。 所以我觉得服务端应该不会不知道客户端已经断开了啊。。。
yyantifa 2013-05-23
  • 打赏
  • 举报
回复
客户端接收数据出现异常,为什么要移除这两个. dict.Remove(sokClient.RemoteEndPoint.ToString()); // 从通信线程集合中删除被中断连接的通信线程对象; dictThread.Remove(sokClient.RemoteEndPoint.ToString()); 监听客户端请求的方法这个应该是服务端. dict.add() dictThread.add() 服务器添加,客户端移除??

110,538

社区成员

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

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

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