C#远程主机强制关闭现有连接:套接字编程

时间:2010-08-02 15:50:39

标签: c# sockets

我正在使用套接字。这是我的代码(问题的描述更进一步):

客户端

    public void ReadCallback(IAsyncResult ar)
    {
        int fileNameLen = 1;
        String content = String.Empty;
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.workSocket;

        int bytesRead = handler.EndReceive(ar);
        if (bytesRead > 0)
        {

            if (flag == 0)
            {

                fileNameLen = BitConverter.ToInt32(state.buffer, 0);
                string fileName = Encoding.UTF8.GetString(state.buffer, 4, fileNameLen);
                receivedPath = mypath + @"XML\";
                if (!Directory.Exists(receivedPath))
                {
                    Directory.CreateDirectory(receivedPath);
                }
                receivedPath = receivedPath + fileName;
                flag++;

            }
            if (flag >= 1)
            {

                BinaryWriter writer = new BinaryWriter(File.Open(receivedPath, FileMode.Append));
                if (flag == 1)
                {
                    writer.Write(state.buffer, 4 + fileNameLen, bytesRead - (4 + fileNameLen));
                    flag++;
                }
                else
                    writer.Write(state.buffer, 0, bytesRead);
                writer.Close();
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReadCallback), state);
            }

        }
        else
        {
            //   Invoke(new MyDelegate(LabelWriter));
        }
    }

我在这一行收到错误:int bytesRead = handler.EndReceive(ar);

如何避免此错误?:An existing connection was forcibly closed by the remote host

服务器端

        public void ReadCallback(IAsyncResult ar)
        {
            try
            {

                int fileNameLen = 1;
                String content = String.Empty;
                StateObject state = (StateObject)ar.AsyncState;
                Socket handler = state.workSocket;
                string[] str = new string[2];
                str = handler.RemoteEndPoint.ToString().Split(':');
                IP = str[0].ToString();
                int bytesRead = handler.EndReceive(ar);

                if (bytesRead > 0)
                {
                    if (flag == 0)
                    {
                        fileNameLen = BitConverter.ToInt32(state.buffer, 0);
                        string fileName = Encoding.UTF8.GetString(state.buffer, 4, fileNameLen);
                        string[] getIP = new string[3];
                        getIP = fileName.Split('_');
                        #region Send Files in HandHeld
                        #region GetLoginFile
                        if (getIP[1].ToString().Equals("GetLoginFile"))
                        {
                            string getDirectory = @"Send_Hand_Held_Files\" + DateTime.Today.ToString("dd-MM-yyyy") + "\\" + getIP[0].ToString() + "\\XML";
                            string strmyFile = getDirectory + "\\Login.xml";
                            char[] delimiter = splitter.ToCharArray();
                            split = strmyFile.Split(delimiter);
                            int limit = split.Length;
                            fName = split[limit - 1].ToString();

                            byte[] LoginfileName = Encoding.UTF8.GetBytes(fName); //file name

                            byte[] fileData = File.ReadAllBytes(strmyFile);

                            byte[] LoginfileNameLen = BitConverter.GetBytes(LoginfileName.Length); //lenght of file name
                            clientData = new byte[4 + LoginfileName.Length + fileData.Length];

                            LoginfileNameLen.CopyTo(clientData, 0);
                            LoginfileName.CopyTo(clientData, 4);
                            fileData.CopyTo(clientData, 4 + LoginfileName.Length);

                            handler.BeginSend(clientData, 0, clientData.Length, 0, new AsyncCallback(SendCallBack), handler);
                            //handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                            //new AsyncCallback(ReadCallback), state);
                            return;
                        }
 }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);

            }
            //SendData(IP);
        }

     private static void SendCallBack(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.
                Socket client = (Socket)ar.AsyncState;

                // Complete sending the data to the remote device.
               // int bytesSent = client.EndSend(ar);
                //Console.WriteLine("Sent {0} bytes to server.", bytesSent);

                // Signal that all bytes have been sent.
                allDone.Set();

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

2 个答案:

答案 0 :(得分:4)

您从handler.EndReceive()收到例外。虽然不确定为什么你接收到你提到的特定异常,但是当投入生产时,每次出现网络通信问题时, 抛出异常。常见)。

因此,你应该对EndReceive()的调用进行try / catch。想想在连接失败或服务器死机或其他什么时你的代码需要做什么。

然后您就可以开始诊断特定问题了。您没有指定的一件重要事情:您是否只是偶尔或者您可以重复地一直获得此错误?如果它是前者,那么它可能只是正常的互联网连接波动。您的软件必须能够处理这些。如果是后者,那么我认为这听起来像服务器上的问题。当您致电BeginReceive()时,您的系统将开始等待来自服务器的内容;如果那个“东西”是它接收到的数据,那么EndReceive()将成功,但如果服务器关闭了连接那么“某事”,你的回调仍将被调用,并且然后EndReceive()会抛出相关的SocketException。这是设计原因,因为几乎没有其他方法可以与服务器关闭连接的代码进行通信。

编辑:您的服务器代码看起来需要相同的错误处理:如果客户端关闭,则对EndReceive()的调用同样容易引发异常连接。 (我知道你有一个尝试/捕捉整个大事,但它输出 MessageBox ...在服务器上不能很好地工作,除非你想要有人一直坐在那里点击所有OK按钮...)

答案 1 :(得分:0)

根据您的错误,我不确定您的代码是否存在问题,可能是在服务器上。除了添加一些状态检查以验证handler.EndReceive(ar)将返回有用的内容之外,您可能需要检查服务器本身(或询问维护它的人这样做)以查看它为什么关闭您的连接。

最后,问题代码可能在您的初始代码中,而不是在此部分:例如,如果对服务器的初始调用太长并导致超时或死锁。