问题描述
情况如下:我从客户端连接server端。连接创建成功,然后,客户端发送一个注册码,server端也能够接收到。然后,server端返回一个成功提示,这时候,报错了。At2014/9/3011:23:03,执行命令内容时出现错误,原因来自于:远程主机强迫关闭了一个现有的连接。在System.Net.Sockets.Socket.Send(Byte[]buffer,Int32offset,Int32size,SocketFlagssocketFlags)在DEC.SocketCommon.SocketCommonObject.SendCommand(SocketsendSocket,Byte[]messageUTF8,Int32commlen,Int32paramlen)位置e:WorkWinForm_Socket_ServerBLLSocketCommonObject.cs:行号73在DEC.SocketCommon.SocketCommonObject.SendCommand(SocketsendSocket,StringcommandText,StringparameText,StringvalueText,BooleanisEncode)位置e:WorkWinForm_Socket_ServerBLLSocketCommonObject.cs:行号38在DEC.SocketServer.SocketServerObject.SendCommand(AsyncUserTokentoken,StringcommandText,StringparameterText,StringvalueText)位置e:WorkWinForm_Socket_ServerSocketServerSocketServerObject.cs:行号301在DEC.SocketServer.SocketServerObject.ProcessCommand(AsyncUserTokentoken,StringstrCommand,StringstrParameter,StringstrValue)位置e:WorkWinForm_Socket_ServerSocketServerSocketServerObject.cs:行号544
客户端是同步的Connect后,用同步的Send方法发送的注册信息。server端是异步的接收,然后用同步的Send方法发送返回信息。server端建立的Socket连接,一直到Send的时候,Connected属性还是TRUE的。但是,一到Send方法,就报上面的错。有比较熟悉.net的Socket开发的哥们给个处理思路么?在我自己机器上客户端和server端都部署,没有任何问题,和同事的机器连接也没问题。就是放到一台服务器上就出毛病,但是对方说服务器没有特别的设置,防火墙什么的都没有(内网服务器)。没什么思路了。。。
解决方案
本帖最后由 yhnxxx 于 2014-09-30 14:42:59 编辑
解决方案二:
对了,是framework2.0的环境。
解决方案三:
boolisConnected=m_autoSocket.Connect();if(isConnected){boolisregister=m_autoSocket.SendRegister(localBusinessInfo);if(!isregister)return;//接收命令boolresult=true;while(result){result=m_autoSocket.ReceiveCommand();}}else{string_message="创建套接字连接失败,请联系管理员!";slog.WriteLog(_message);}
客户端的连接代码。
解决方案四:
服务端的接收和反馈代码。case"register":#region注册//将注册信息写入到本地文件中记录token.SocketID=scommon.RegisterClientSocket(strValue,token.Socket.RemoteEndPoint.ToString());//将远程端的验证码返回给client端stringremoteSecurity=scommon.GetSecurityCode(strValue);slog.WriteLog("处理注册连接"+token.SocketID);slog.WriteLog("处理注册连接"+token.Socket.Connected.ToString());slog.WriteLog("处理注册连接"+token.ActiveDateTime.ToString());slog.WriteLog("注册码"+remoteSecurity);this.SendCommand(token,strCommand,strParameter,remoteSecurity);
解决方案五:
服务端this.SendCommand(token,strCommand,strParameter,remoteSecurity);有问题,你把this换成客户端连接的socket对象
解决方案六:
引用4楼sunny906的回复:
服务端this.SendCommand(token,strCommand,strParameter,remoteSecurity);有问题,你把this换成客户端连接的socket对象
是这样,我在外面用token把Socket对象封装了一下,这里的SendCommand方法是封装后的,传入封装的token就可以,最终是用这句发送的。intsendbytes=sendSocket.Send(m_sendBuffer.Buffer,0,totalLength,SocketFlags.None);
解决方案七:
this是不是正在使用的socket对象?
解决方案八:
1、不要用if(socket.Connected)来判断socket的连接状态,因为这个Connected并不能正确地反映客户端跟服务端的连接是否处于正常连接状态;客户端的其他代码倒没什么问题2、服务端开启侦听之后,需要不断地接收来自客户端的连接while(true){Sockets=socket.Accept();s.BeginReceive(buffer,0,buffer.Length,SocketFlags.None,newAsyncCallback((IAsyncResultir)=>{//处理客户端发送的数据//...s.Send(buffer);//向客户端发送响应的数据}),null);}
代码只是一些示例,当然要做的处理不止这些,比如异常处理,对接收数据的处理等等
解决方案九:
引用7楼sunny906的回复:
1、不要用if(socket.Connected)来判断socket的连接状态,因为这个Connected并不能正确地反映客户端跟服务端的连接是否处于正常连接状态;客户端的其他代码倒没什么问题2、服务端开启侦听之后,需要不断地接收来自客户端的连接………………
处理的思路我是明白的。现在就是个细节问题。我发下客户端和server端的日志,你对比看一下,就知道了。我在server端用netstat查看连接也是已连接状态。客户端:At2014-9-3010:07:21,新的套接字已成功连接.本地:172.16.0.247:4525远端:172.16.3.145:9998At2014-9-3010:07:21,套接字连接发送了244bytes.本地:172.16.0.247:4525远端:172.16.3.145:9998命令为:RegisterAt2014-9-3010:10:55,远程主机强迫关闭了一个现有的连接。atSystem.Net.Sockets.Socket.Receive(Byte[]buffer,Int32offset,Int32size,SocketFlagssocketFlags)atSystem.Net.Sockets.Socket.Receive(Byte[]buffer)atDEC.SocketClient.SocketClientObject.ReceiveCommand()At2014-9-3010:11:21,连接关闭方法被调用,连接被关闭reconnectTimer_TickAt2014-9-3010:11:21,连接关闭方法被调用,连接进程被关闭reconnectTimer_Tick2At2014-9-3010:11:21,新的套接字已成功连接.本地:172.16.0.247:4548远端:172.16.3.145:9998服务端:At2014/9/3010:06:44,新的套接字连接已经接入.At2014/9/3010:06:45,执行命令内容时出现错误,原因来自于:远程主机强迫关闭了一个现有的连接。在System.Net.Sockets.Socket.Send(Byte[]buffer,Int32offset,Int32size,SocketFlagssocketFlags)在DEC.SocketCommon.SocketCommonObject.SendCommand(SocketsendSocket,Byte[]messageUTF8,Int32commlen,Int32paramlen)在DEC.SocketCommon.SocketCommonObject.SendCommand(SocketsendSocket,StringcommandText,StringparameText,StringvalueText,BooleanisEncode)在DEC.SocketServer.SocketServerObject.SendCommand(AsyncUserTokentoken,StringcommandText,StringparameterText,StringvalueText)在DEC.SocketServer.SocketServerObject.ProcessCommand(AsyncUserTokentoken,StringstrCommand,StringstrParameter,StringstrValue)At2014/9/3010:06:45,套接字连接序号为:【3-来自数据服务器】.接收了:244bytes.本地:0.0.0.0:9998远端:172.16.0.247:4525命令为:RegisterAt2014/9/3010:10:44,新的套接字连接已经接入.******客户端的时间快40多秒*****
解决方案十:
引用6楼FoxDave的回复:
this是不是正在使用的socket对象?
是封装后的对象。
解决方案十一:
那正常不应该出问题的啊你再仔细看一下是不是主动关闭了
解决方案十二:
看日志应该是服务端向客户端发送数据的时候,客户端就已经跟服务端断开连接了。客户端的发送完数据后,有没有调用Shutdown()
解决方案十三:
e:WorkWinForm_Socket_ServerBLLSocketCommonObject.cs:行号73m_autoSocket.ReceiveCommand();的代码?
解决方案十四:
我还有个小疑问,“本地:0.0.0.0:9998”这个是对的么?为什么我自己测试的时候,显示的是真实IP,到了这里变成了0.0.0.0了。。。都是读取的LocalEndPoint。
解决方案十五:
引用12楼sxldfang的回复:
e:WorkWinForm_Socket_ServerBLLSocketCommonObject.cs:行号73m_autoSocket.ReceiveCommand();的代码?
if(m_first_tcpClient==null||!m_first_tcpClient.Connected)returnfalse;#region解析包intrevbuff_offset=0;do{byte[]tmpreceive=newbyte[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);//eventif(SocketReceived!=null){SocketReceived(this,newSocketEventArgs(m_syncUserToken));}//更新活跃时间点m_syncUserToken.ActiveDateTime=DateTime.Now;//处理命令和命令内容boolresult=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();returnfalse;}#endregionthis.m_syncUserToken.ReceiveBuffer.Clear();this.m_syncUserToken.ReceiveBuffer.Buffer=newbyte[0];//投递下次请求//this.ReceiveCommand();returntrue;
在关闭连接的地方,我都插入了日志,没有记录到是程序内部主动关闭的。
解决方案:
引用11楼sunny906的回复:
看日志应该是服务端向客户端发送数据的时候,客户端就已经跟服务端断开连接了。客户端的发送完数据后,有没有调用Shutdown()
try{//开始运行m_autoSocket=newSocketClientObject();m_autoSocket.SocketTimeOutMS=(int)m_socketTimeOut;m_autoSocket.StartTime=DateTime.Now;m_autoSocket.SocketConnected+=newEventHandler<SocketEventArgs>(Socket_Connected);m_autoSocket.SocketReceived+=newEventHandler<SocketEventArgs>(Socket_Received);m_autoSocket.SocketSended+=newEventHandler<SocketEventArgs>(Socket_Send);m_autoSocket.SocketDisConnected+=newEventHandler<SocketEventArgs>(Socket_DisConnected);//连接Socket服务端//并发送自描述信息/*该信息包括:*①本机mac地址*②本机相关业务信息*/GetUserFace();//将"用户信息"拼写为xml格式内容stringlocalBusinessInfo=GetUserInfoByXML();boolisConnected=m_autoSocket.Connect();if(isConnected){boolisregister=m_autoSocket.SendRegister(localBusinessInfo);if(!isregister)return;//接收命令boolresult=true;while(result){result=m_autoSocket.ReceiveCommand();}}else{string_message="创建套接字连接失败,请联系管理员!";slog.WriteLog(_message);}}catch(SocketExceptionsex){if(sex.ErrorCode==10004){slog.WriteLog(sex.Message);}elseif(sex.ErrorCode==10061||sex.ErrorCode==10060)//server端服务未启动{slog.WriteLog("无法创建套接字连接,原因来自于:"+sex.Message);MessageBox.Show("无法创建套接字连接,原因来自于:无法连接远程服务器或远程服务未开启。请联系管理员。");NullObjectEventHandlernullobj=delegate(){setStartAndStopButton(true);};btnStart.Invoke(nullobj);WriteLog("Start_1");CloseAndStop();}else{MessageBox.Show("无法创建套接字连接,请将以下错误信息发送给管理员。错误信息:"+sex.Message);slog.WriteLog(sex.Message+sex.StackTrace);NullObjectEventHandlernullobj=delegate(){setStartAndStopButton(true);};WriteLog("Start_2");btnStart.Invoke(nullobj);CloseAndStop();}}catch(Exceptionex){MessageBox.Show("无法创建套接字连接,请将以下错误信息发送给管理员。错误信息:"+ex.Message);slog.WriteLog(ex.Message+ex.StackTrace);NullObjectEventHandlernullobj=delegate(){setStartAndStopButton(true);};btnStart.Invoke(nullobj);WriteLog("Start_3");CloseAndStop();}
只在catch里面有关闭动作,但是日志并没有记录到有错误发生。
解决方案:
引用13楼yhnxxx的回复:
我还有个小疑问,“本地:0.0.0.0:9998”这个是对的么?为什么我自己测试的时候,显示的是真实IP,到了这里变成了0.0.0.0了。。。都是读取的LocalEndPoint。
这个没问题,在客户端显示的IPAddress.Any,到了服务端会被自动解析成真实的客户端IP
解决方案:
你把这些事件先注释掉看看,可能某个事件被触发引起客户端的连接关闭m_autoSocket.SocketConnected+=newEventHandler<SocketEventArgs>(Socket_Connected);m_autoSocket.SocketReceived+=newEventHandler<SocketEventArgs>(Socket_Received);m_autoSocket.SocketSended+=newEventHandler<SocketEventArgs>(Socket_Send);m_autoSocket.SocketDisConnected+=newEventHandler<SocketEventArgs>(Socket_DisConnected);
解决方案:
我这边又测试了一下,发现了导致我这个问题的点:服务端创建监听的时候,使用的是msdn推荐的:IPEndPointiepclient=newIPEndPoint(IPAddress.Any,m_listenningClientPort)listenSocket=newSystem.Net.Sockets.Socket(localEndPoint.AddressFamily,SocketType.Stream,ProtocolType.Tcp);listenSocket.Bind(localEndPoint);
问题就在这里:我后来改成了真实的IP地址:IPEndPointiepclient=newIPEndPoint("172.16.3.145",m_listenningClientPort)listenSocket=newSystem.Net.Sockets.Socket(localEndPoint.AddressFamily,SocketType.Stream,ProtocolType.Tcp);listenSocket.Bind(localEndPoint);
问题就消失了。。。但是,很让人费解的一点是,从IPAddress.Any自身的意义,以及官方的解释来看,用IPAddress.Any都没有问题。。。。为什么我这里就非要指定具体的IP呢?有高人指点一下么?谢谢!
解决方案:
引用17楼sunny906的回复:
你把这些事件先注释掉看看,可能某个事件被触发引起客户端的连接关闭
哥们遇到过这种问题么?
解决方案:
引用19楼yhnxxx的回复:
Quote: 引用17楼sunny906的回复:
你把这些事件先注释掉看看,可能某个事件被触发引起客户端的连接关闭哥们遇到过这种问题么?
这个问题是不是和网络结构有关?我对这个不太熟,希望高人指点一下!
解决方案:
引用18楼yhnxxx的回复:
我这边又测试了一下,发现了导致我这个问题的点:服务端创建监听的时候,使用的是msdn推荐的:IPEndPointiepclient=newIPEndPoint(IPAddress.Any,m_listenningClientPort)listenSocket=newSystem.Net.Sockets.Socket(localEndPoint.AddressFamily,SocketType.Stream,ProtocolType.Tcp);listenSocket.Bind(localEndPoint);问题就在这里:我后来改成了真实的IP地址:IPEndPointiepclient=newIPEndPoint("172.16.3.145",m_listenningClientPort)listenSocket=newSystem.Net.Sockets.Socket(localEndPoint.AddressFamily,SocketType.Stream,ProtocolType.Tcp);listenSocket.Bind(localEndPoint);
问题就消失了。。。但是,很让人费解的一点是,从IPAddress.Any自身的意义,以及官方的解释来看,用IPAddress.Any都没有问题。。。。为什么我这里就非要指定具体的IP呢?有高人指点一下么?谢谢!
iepclient这个东东,在后面的代码里也没用上啊??你是否接受的socket和发送的socket不是同一个对象??
解决方案:
引用楼主yhnxxx的回复:
server端建立的Socket连接,一直到Send的时候,Connected属性还是TRUE的。但是,一到Send方法,就报上面的错。有比较熟悉.net的Socket开发的哥们给个处理思路么?
connected不是给你检测当前连线情况,是告诉你上一次收发消息情况。除非你发一条消息,否则没有什么办法告诉你当前是否connected。
解决方案:
引用18楼yhnxxx的回复:
我这边又测试了一下,发现了导致我这个问题的点:服务端创建监听的时候,使用的是msdn推荐的:IPEndPointiepclient=newIPEndPoint(IPAddress.Any,m_listenningClientPort)listenSocket=newSystem.Net.Sockets.Socket(localEndPoint.AddressFamily,SocketType.Stream,ProtocolType.Tcp);listenSocket.Bind(localEndPoint);问题就在这里:我后来改成了真实的IP地址:IPEndPointiepclient=newIPEndPoint("172.16.3.145",m_listenningClientPort)listenSocket=newSystem.Net.Sockets.Socket(localEndPoint.AddressFamily,SocketType.Stream,ProtocolType.Tcp);listenSocket.Bind(localEndPoint);
问题就消失了。。。但是,很让人费解的一点是,从IPAddress.Any自身的意义,以及官方的解释来看,用IPAddress.Any都没有问题。。。。为什么我这里就非要指定具体的IP呢?有高人指点一下么?谢谢!
你那里使用iepclient了?你不是写Bind(localEndPoint)这个嘛。那么你改这个有什么用呢?
解决方案:
你的运行环境是不是有UCA控制啊?尝试一下以管理员模式运行。