当前位置:编程学习 > C#/ASP.NET >>

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

我先说一下我现在发现的情况,我借助网上的实例编写了一个服务器测试程序。
有一个后台线程,负责监听客户端的连接,如果有请求,就会建立一个连接,同时产生一个前台的接收线程接收数据。
对于一个在服务器端已成功建立连接的客户端,能够实现正常的通讯。在非通讯状态下,客户端意外的断开了连接,没有通知服务器,服务器并不知道该客户端已断开。为了实现连接,客户端会再次向服务器发起连接请求,当服务器端收到连接请求的时候,会提示“客户端强行关闭连接”。客户端再次向服务器发起连接请求,服务器接收,建立连接,并产生接收线程。
问题:
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);//显示到指定的控件中 自定方法                     
    }
}
C# Socket 断点续连 --------------------编程问答-------------------- 客户端接收数据出现异常,为什么要移除这两个.
dict.Remove(sokClient.RemoteEndPoint.ToString());
 // 从通信线程集合中删除被中断连接的通信线程对象;   
dictThread.Remove(sokClient.RemoteEndPoint.ToString());


监听客户端请求的方法这个应该是服务端.
dict.add()
dictThread.add()

服务器添加,客户端移除?? --------------------编程问答--------------------     看了下我以前写的客户端和服务端,正常关闭客户端的时候,会发送个断开连接的数据给服务端,如果强行结束客户端的进程,服务端就会报错。。。应该加个Try吧,然后把连接的线程关了就好。
    所以我觉得服务端应该不会不知道客户端已经断开了啊。。。
--------------------编程问答-------------------- 1.一个socket连接是包含了服务器IP+PORT + 客户端IP+PORT,对于已经建立的连接,那是会拒绝的
  (端口复用的情况没试验过,不知道是什么状况)
2.既然无法连接,那么服务器也就不知道客户端请求连接的情况。所以无法实现,
以上是个人想法。

一般处理方法:
1.客户端发送心跳包到服务器
2.服务器使用一个检测线程用来检查每个连接,在规定时间内,没有收到任何包,则认为该连接无效,关闭之

没有看到你客户端的连接代码,不知道你是否绑定了客户端本地的IP和端口,若是没有的话,那么每次连接系统会自动选择合适的端口与服务器建立连接,所以服务器仅仅靠每个客户端的IP+PORT来管理是不合适的。
--------------------编程问答--------------------
引用 1 楼 yyantifa 的回复:
客户端接收数据出现异常,为什么要移除这两个.
dict.Remove(sokClient.RemoteEndPoint.ToString());
 // 从通信线程集合中删除被中断连接的通信线程对象;   
dictThread.Remove(sokClient.RemoteEndPoint.ToString());


监听客户端请求的方法这个应该是服务端.
dict.add()
dictThread.add()

服务器添加,客户端移除?? 


您可能没有看明白,我上面的是服务器端代码,对于无效的连接,自然要移除了。保留无效的连接,在通讯的时候会出异常的。 --------------------编程问答--------------------
引用 2 楼 dixh1989 的回复:
    看了下我以前写的客户端和服务端,正常关闭客户端的时候,会发送个断开连接的数据给服务端,如果强行结束客户端的进程,服务端就会报错。。。应该加个Try吧,然后把连接的线程关了就好。
    所以我觉得服务端应该不会不知道客户端已经断开了啊。。。
 


您可能也是没看太明白,我说的是意外断开连接,并没有给服务器端发送断开请求,说的就是非正常的断连。
比如客户端突然掉电,或网络物理断连等等非正常的情况。 --------------------编程问答-------------------- 想学,关注,并帮楼主顶 --------------------编程问答--------------------
引用 3 楼 wodegege10 的回复:
1.一个socket连接是包含了服务器IP+PORT + 客户端IP+PORT,对于已经建立的连接,那是会拒绝的
  (端口复用的情况没试验过,不知道是什么状况)
2.既然无法连接,那么服务器也就不知道客户端请求连接的情况。所以无法实现,
以上是个人想法。

一般处理方法:
1.客户端发送心跳包到服务器
2.服务器使用一个检测线程用来检查每个连接,在规定时间内,没有收到任何包,则认为该连接无效,关闭之

没有看到你客户端的连接代码,不知道你是否绑定了客户端本地的IP和端口,若是没有的话,那么每次连接系统会自动选择合适的端口与服务器建立连接,所以服务器仅仅靠每个客户端的IP+PORT来管理是不合适的。


谢谢您的回复!我对这部分也确实不是很精通,还在学习中。
我没有对客户端太过研究是由于实际情况是,我的客户端是一个硬件设备。目前,这个硬件设备只有上电或复位的时候,才发一个连接请求。但是每次意外断连后,都得重新上电两次,才能重新和我机器上的服务器建立连接,所以才想问问能否一次来解决,在不考虑服务器发现客户端的连接无效的情况下。
如果一次的方式无法解决,那服务器端就得通过其它方式来关闭连接,并等待连接请求,比如心跳,通讯超时等等。不过这个都和这个帖子的本意无关了,都是后话。
发过贴后,自己也想了想在意外断连后,为什么是接收线程发现的异常,而监控监听线程没有结果。
虽然客户端断开了,但是服务器不知道,当客户端发起连接请求的时候,服务器端认为是该客户端的一条通讯数据,所以是接收线程收到数据,监听线程没有收到(也很疑惑是否认为正确),但是接收线程还没有那么高的权限来处理这条数据,感觉有点像把父亲的工作交给了儿子,儿子处理不了,所以发起异常,并自行关闭该连接。
以上也是个人想法,并没有理论依据。

不知还有高人有自己的想法吗?分享一下啊? --------------------编程问答--------------------
引用 6 楼 Mic_Gary 的回复:
想学,关注,并帮楼主顶 


谢谢帮顶!!
单位电脑太悲催,连引用都无法出现。
没办法,上别人电脑看看引用的格式,自己编辑引用,累啊! --------------------编程问答--------------------
我等啊等,我等啊等,……
补充:.NET技术 ,  C#
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,