在线等。Socket从客户端连接后,服务端无法返回内容,报错。

鼻涕蛋蛋 2014-09-30 02:39:50
情况如下:
我从客户端连接server端。连接创建成功,然后,客户端发送一个注册码,server端也能够接收到。然后,server端返回一个成功提示,这时候,报错了。

At 2014/9/30 11:23:03 , 执行命令内容时出现错误 , 原因来自于 : 远程主机强迫关闭了一个现有的连接。 在 System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
在 DEC.SocketCommon.SocketCommonObject.SendCommand(Socket sendSocket, Byte[] messageUTF8, Int32 commlen, Int32 paramlen) 位置 e:\Work\WinForm_Socket_Server\BLL\SocketCommonObject.cs:行号 73
在 DEC.SocketCommon.SocketCommonObject.SendCommand(Socket sendSocket, String commandText, String parameText, String valueText, Boolean isEncode) 位置 e:\Work\WinForm_Socket_Server\BLL\SocketCommonObject.cs:行号 38
在 DEC.SocketServer.SocketServerObject.SendCommand(AsyncUserToken token, String commandText, String parameterText, String valueText) 位置 e:\Work\WinForm_Socket_Server\SocketServer\SocketServerObject.cs:行号 301
在 DEC.SocketServer.SocketServerObject.ProcessCommand(AsyncUserToken token, String strCommand, String strParameter, String strValue) 位置 e:\Work\WinForm_Socket_Server\SocketServer\SocketServerObject.cs:行号 544

客户端是同步的Connect后,用同步的Send方法发送的注册信息。
server端是异步的接收,然后用同步的Send方法发送返回信息。
server端建立的Socket连接,一直到Send的时候,Connected属性还是TRUE的。但是,一到Send方法,就报上面的错。
有比较熟悉.net的Socket开发的哥们给个处理思路么?
在我自己机器上客户端和server端都部署,没有任何问题,和同事的机器连接也没问题。就是放到一台服务器上就出毛病,但是对方说服务器没有特别的设置,防火墙什么的都没有(内网服务器)。
没什么思路了。。。
...全文
732 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
robake 2014-10-01
  • 打赏
  • 举报
回复
你的运行环境是不是有UCA控制啊?尝试一下以管理员模式运行。
  • 打赏
  • 举报
回复
引用 18 楼 yhnxxx 的回复:
我这边又测试了一下,发现了导致我这个问题的点: 服务端创建监听的时候,使用的是msdn推荐的:

IPEndPoint iepclient = new IPEndPoint(IPAddress.Any, m_listenningClientPort)
listenSocket = new System.Net.Sockets.Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(localEndPoint);
问题就在这里: 我后来改成了真实的IP地址:

IPEndPoint iepclient = new IPEndPoint("172.16.3.145", m_listenningClientPort)
listenSocket = new System.Net.Sockets.Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(localEndPoint);
问题就消失了。。。 但是,很让人费解的一点是,从IPAddress.Any自身的意义,以及官方的解释来看,用IPAddress.Any都没有问题。。。。 为什么我这里就非要指定具体的IP呢?有高人指点一下么?谢谢!
你那里使用 iepclient 了?你不是写 Bind(localEndPoint) 这个嘛。那么你改这个有什么用呢?
  • 打赏
  • 举报
回复
引用 楼主 yhnxxx 的回复:
server端建立的Socket连接,一直到Send的时候,Connected属性还是TRUE的。但是,一到Send方法,就报上面的错。 有比较熟悉.net的Socket开发的哥们给个处理思路么?
connected 不是给你检测当前连线情况,是告诉你上一次收发消息情况。除非你发一条消息,否则没有什么办法告诉你当前是否connected。
於黾 2014-09-30
  • 打赏
  • 举报
回复
引用 18 楼 yhnxxx 的回复:
我这边又测试了一下,发现了导致我这个问题的点: 服务端创建监听的时候,使用的是msdn推荐的:

IPEndPoint iepclient = new IPEndPoint(IPAddress.Any, m_listenningClientPort)
listenSocket = new System.Net.Sockets.Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(localEndPoint);
问题就在这里: 我后来改成了真实的IP地址:

IPEndPoint iepclient = new IPEndPoint("172.16.3.145", m_listenningClientPort)
listenSocket = new System.Net.Sockets.Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(localEndPoint);
问题就消失了。。。 但是,很让人费解的一点是,从IPAddress.Any自身的意义,以及官方的解释来看,用IPAddress.Any都没有问题。。。。 为什么我这里就非要指定具体的IP呢?有高人指点一下么?谢谢!
iepclient这个东东,在后面的代码里也没用上啊?? 你是否接受的socket和发送的socket不是同一个对象??
鼻涕蛋蛋 2014-09-30
  • 打赏
  • 举报
回复
引用 19 楼 yhnxxx 的回复:
[quote=引用 17 楼 sunny906 的回复:] 你把这些事件先注释掉看看,可能某个事件被触发引起客户端的连接关闭
哥们遇到过这种问题么?[/quote] 这个问题是不是和网络结构有关?我对这个不太熟,希望高人指点一下!
鼻涕蛋蛋 2014-09-30
  • 打赏
  • 举报
回复
引用 17 楼 sunny906 的回复:
你把这些事件先注释掉看看,可能某个事件被触发引起客户端的连接关闭
哥们遇到过这种问题么?
鼻涕蛋蛋 2014-09-30
  • 打赏
  • 举报
回复
我这边又测试了一下,发现了导致我这个问题的点: 服务端创建监听的时候,使用的是msdn推荐的:

IPEndPoint iepclient = new IPEndPoint(IPAddress.Any, m_listenningClientPort)
listenSocket = new System.Net.Sockets.Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(localEndPoint);
问题就在这里: 我后来改成了真实的IP地址:

IPEndPoint iepclient = new IPEndPoint("172.16.3.145", m_listenningClientPort)
listenSocket = new System.Net.Sockets.Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(localEndPoint);
问题就消失了。。。 但是,很让人费解的一点是,从IPAddress.Any自身的意义,以及官方的解释来看,用IPAddress.Any都没有问题。。。。 为什么我这里就非要指定具体的IP呢?有高人指点一下么?谢谢!
sunny906 2014-09-30
  • 打赏
  • 举报
回复
你把这些事件先注释掉看看,可能某个事件被触发引起客户端的连接关闭

                m_autoSocket.SocketConnected += new EventHandler<SocketEventArgs>(Socket_Connected);
                m_autoSocket.SocketReceived += new EventHandler<SocketEventArgs>(Socket_Received);
                m_autoSocket.SocketSended += new EventHandler<SocketEventArgs>(Socket_Send);
                m_autoSocket.SocketDisConnected += new EventHandler<SocketEventArgs>(Socket_DisConnected);
                
sunny906 2014-09-30
  • 打赏
  • 举报
回复
引用 13 楼 yhnxxx 的回复:
我还有个小疑问,“本地 : 0.0.0.0:9998”这个是对的么?为什么我自己测试的时候,显示的是真实IP,到了这里变成了0.0.0.0了。。。都是读取的LocalEndPoint。
这个没问题,在客户端显示的IPAddress.Any,到了服务端会被自动解析成真实的客户端IP
鼻涕蛋蛋 2014-09-30
  • 打赏
  • 举报
回复
引用 11 楼 sunny906 的回复:
看日志应该是服务端向客户端发送数据的时候,客户端就已经跟服务端断开连接了。客户端的发送完数据后,有没有调用Shutdown()

try
            {
                //开始运行
                m_autoSocket = new SocketClientObject();
                m_autoSocket.SocketTimeOutMS = (int)m_socketTimeOut;
                m_autoSocket.StartTime = DateTime.Now;
                m_autoSocket.SocketConnected += new EventHandler<SocketEventArgs>(Socket_Connected);
                m_autoSocket.SocketReceived += new EventHandler<SocketEventArgs>(Socket_Received);
                m_autoSocket.SocketSended += new EventHandler<SocketEventArgs>(Socket_Send);
                m_autoSocket.SocketDisConnected += new EventHandler<SocketEventArgs>(Socket_DisConnected);
                //连接Socket服务端
                //并发送自描述信息
                /*该信息包括:
                 * ①本机mac地址
                 * ②本机相关业务信息
                 */
                GetUserFace();
                //将"用户信息"拼写为xml格式内容
                string localBusinessInfo = GetUserInfoByXML();
                bool isConnected = m_autoSocket.Connect();

                if (isConnected)
                {
                    bool isregister = m_autoSocket.SendRegister(localBusinessInfo);
                    if (!isregister) return;
                    //接收命令
                    bool result = true;
                    while (result)
                    {
                        result = m_autoSocket.ReceiveCommand();
                    }
                    
                }
                else
                {
                    string _message = "创建套接字连接失败 , 请联系管理员 ! ";                   
                    slog.WriteLog(_message);
                }
            }
            catch (SocketException sex)
            {
                if (sex.ErrorCode == 10004)
                {
                    slog.WriteLog(sex.Message);
                }
                else if (sex.ErrorCode == 10061 || sex.ErrorCode == 10060)//server端服务未启动
                {
                    slog.WriteLog("无法创建套接字连接 , 原因来自于 :" + sex.Message);
                    MessageBox.Show("无法创建套接字连接 , 原因来自于 : 无法连接远程服务器或远程服务未开启。请联系管理员。");
                    NullObjectEventHandler nullobj = delegate()
                    {
                        setStartAndStopButton(true);
                    };

                    btnStart.Invoke(nullobj);
                    WriteLog("Start_1");
                    CloseAndStop();
                }
                else
                {
                    MessageBox.Show("无法创建套接字连接 , 请将以下错误信息发送给管理员。错误信息 : " + sex.Message);
                    slog.WriteLog(sex.Message + sex.StackTrace);
                    NullObjectEventHandler nullobj = delegate()
                    {
                        setStartAndStopButton(true);
                    };
                    WriteLog("Start_2");
                    btnStart.Invoke(nullobj);
                    CloseAndStop();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("无法创建套接字连接 , 请将以下错误信息发送给管理员。错误信息 : " + ex.Message);
                slog.WriteLog(ex.Message + ex.StackTrace);
                NullObjectEventHandler nullobj = delegate()
                {
                    setStartAndStopButton(true);
                };

                btnStart.Invoke(nullobj);
                WriteLog("Start_3");
                CloseAndStop();
            }
只在catch里面有关闭动作,但是日志并没有记录到有错误发生。
鼻涕蛋蛋 2014-09-30
  • 打赏
  • 举报
回复
引用 12 楼 sxldfang 的回复:
e:\Work\WinForm_Socket_Server\BLL\SocketCommonObject.cs:行号 73 m_autoSocket.ReceiveCommand();的代码?

if (m_first_tcpClient == null || !m_first_tcpClient.Connected) return false;

                #region 解析包
                int revbuff_offset = 0;
                do
                {
                    byte[] tmpreceive = new byte[ProtocolConst.ReceiveBufferSize];
                    revbuff_offset = m_first_tcpClient.Receive(tmpreceive);

                    this.m_syncUserToken.ReceiveBuffer.WriteBuffer(tmpreceive, m_syncUserToken.ReceiveBuffer.DataCount, revbuff_offset);

                } while (!this.DecodePacket(this.m_syncUserToken));
                slog.WriteLog("接收到了" + m_syncUserToken.ReceiveBuffer.DataCount .ToString()+ "字节");
                if (m_syncUserToken.ReceiveBuffer.DataCount > 0)
                {
                    //按照长度取回解码后的命令、参数和值
                    m_command = ProtocolCommon.GetCommandTextUTF8(this.m_syncUserToken.ReceiveBuffer.Buffer, 0);
                    m_parameters = ProtocolCommon.GetParametersUTF8(this.m_syncUserToken.ReceiveBuffer.Buffer, 0);
                    m_values = ProtocolCommon.GetValuesUTF8(this.m_syncUserToken.ReceiveBuffer.Buffer, 0);

                    //event
                    if (SocketReceived != null)
                    {
                        SocketReceived(this, new SocketEventArgs(m_syncUserToken));
                    }
                    //更新活跃时间点
                    m_syncUserToken.ActiveDateTime = DateTime.Now;
                    //处理命令和命令内容
                    bool result = this.ProcessCommand(m_command, m_parameters, m_values);
                }
                else
                {
                    slog.WriteLog(string.Format("远程服务器主动关闭了连接 , 本地 :{0} 远端 :{1}", m_first_tcpClient.LocalEndPoint.ToString(), m_first_tcpClient.RemoteEndPoint.ToString()));
                    ClosedSocketClient();
                    return false;
                }
                #endregion

                this.m_syncUserToken.ReceiveBuffer.Clear();
                this.m_syncUserToken.ReceiveBuffer.Buffer = new byte[0];

                //投递下次请求
                //this.ReceiveCommand();
                return true;
在关闭连接的地方,我都插入了日志,没有记录到是程序内部主动关闭的。
鼻涕蛋蛋 2014-09-30
  • 打赏
  • 举报
回复
我还有个小疑问,“本地 : 0.0.0.0:9998”这个是对的么?为什么我自己测试的时候,显示的是真实IP,到了这里变成了0.0.0.0了。。。都是读取的LocalEndPoint。
sxldfang 2014-09-30
  • 打赏
  • 举报
回复
e:\Work\WinForm_Socket_Server\BLL\SocketCommonObject.cs:行号 73 m_autoSocket.ReceiveCommand();的代码?
sunny906 2014-09-30
  • 打赏
  • 举报
回复
看日志应该是服务端向客户端发送数据的时候,客户端就已经跟服务端断开连接了。客户端的发送完数据后,有没有调用Shutdown()
Justin-Liu 2014-09-30
  • 打赏
  • 举报
回复
那正常不应该出问题的啊 你再仔细看一下是不是主动关闭了
鼻涕蛋蛋 2014-09-30
  • 打赏
  • 举报
回复
引用 6 楼 FoxDave 的回复:
this是不是正在使用的socket对象?
是封装后的对象。
鼻涕蛋蛋 2014-09-30
  • 打赏
  • 举报
回复
引用 7 楼 sunny906 的回复:
1、不要用 if (socket.Connected)来判断socket的连接状态,因为这个Connected并不能正确地反映客户端跟服务端的连接是否处于正常连接状态;客户端的其他代码倒没什么问题 2、服务端开启侦听之后,需要不断地接收来自客户端的连接 ………………
处理的思路我是明白的。现在就是个细节问题。我发下客户端和server端的日志,你对比看一下,就知道了。我在server 端用netstat查看连接也是已连接状态。 客户端: At 2014-9-30 10:07:21 , 新的套接字已成功连接. 本地 : 172.16.0.247:4525 远端 : 172.16.3.145:9998 At 2014-9-30 10:07:21 , 套接字连接发送了 244 bytes.本地 : 172.16.0.247:4525 远端 : 172.16.3.145:9998 命令为 : Register At 2014-9-30 10:10:55 , 远程主机强迫关闭了一个现有的连接。 at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) at System.Net.Sockets.Socket.Receive(Byte[] buffer) at DEC.SocketClient.SocketClientObject.ReceiveCommand() At 2014-9-30 10:11:21 , 连接关闭方法被调用,连接被关闭reconnectTimer_Tick At 2014-9-30 10:11:21 , 连接关闭方法被调用,连接进程被关闭reconnectTimer_Tick2 At 2014-9-30 10:11:21 , 新的套接字已成功连接. 本地 : 172.16.0.247:4548 远端 : 172.16.3.145:9998 服务端: At 2014/9/30 10:06:44 , 新的套接字连接已经接入. At 2014/9/30 10:06:45 , 执行命令内容时出现错误 , 原因来自于 : 远程主机强迫关闭了一个现有的连接。 在 System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) 在 DEC.SocketCommon.SocketCommonObject.SendCommand(Socket sendSocket, Byte[] messageUTF8, Int32 commlen, Int32 paramlen) 在 DEC.SocketCommon.SocketCommonObject.SendCommand(Socket sendSocket, String commandText, String parameText, String valueText, Boolean isEncode) 在 DEC.SocketServer.SocketServerObject.SendCommand(AsyncUserToken token, String commandText, String parameterText, String valueText) 在 DEC.SocketServer.SocketServerObject.ProcessCommand(AsyncUserToken token, String strCommand, String strParameter, String strValue) At 2014/9/30 10:06:45 , 套接字连接序号为 :【3 - 来自数据服务器】. 接收了 : 244 bytes. 本地 : 0.0.0.0:9998 远端 : 172.16.0.247:4525 命令为 : Register At 2014/9/30 10:10:44 , 新的套接字连接已经接入. ******客户端的时间快40多秒*****
sunny906 2014-09-30
  • 打赏
  • 举报
回复
1、不要用 if (socket.Connected)来判断socket的连接状态,因为这个Connected并不能正确地反映客户端跟服务端的连接是否处于正常连接状态;客户端的其他代码倒没什么问题 2、服务端开启侦听之后,需要不断地接收来自客户端的连接

            while (true)
            {
                Socket s = socket.Accept();
                s.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None,
                    new AsyncCallback((IAsyncResult ir) =>
                    {
                        //处理客户端发送的数据
                        //...
                        s.Send(buffer); //向客户端发送响应的数据
                    }), null);
            }
代码只是一些示例,当然要做的处理不止这些,比如异常处理,对接收数据的处理等等
Justin-Liu 2014-09-30
  • 打赏
  • 举报
回复
this是不是正在使用的socket对象?
鼻涕蛋蛋 2014-09-30
  • 打赏
  • 举报
回复
引用 4 楼 sunny906 的回复:
服务端this.SendCommand(token, strCommand, strParameter, remoteSecurity);有问题,你把this换成客户端连接的socket对象
是这样,我在外面用token把Socket对象封装了一下,这里的SendCommand方法是封装后的,传入封装的token就可以,最终是用这句发送的。
 int sendbytes = sendSocket.Send(m_sendBuffer.Buffer, 0, totalLength, SocketFlags.None);
加载更多回复(4)

110,538

社区成员

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

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

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