C# TCP Socket error - 10060

2019-03-04 15:16发布

问题:

I have a windows service act as a server. And I run one windows form application form localhost as a client. Both the programs use TCP socket connection to send/recieve data. Server listens on port 8030. The program works fine.

BUt when I enhanced the client program to communicate on specific port let's say 9030. While getting connected to server it generates the following exception.

A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 192.168.10.198:8030

Any suggestion will be highly appreciated.

Thanks, Madhusmita

For refrence

Server Program Code

public partial class TestService : ServiceBase
{
    Socket serverSocket = null;
    public Timer timer1;
    IPEndPoint ipEndPoint;

    public TestService()
    {
        InitializeComponent();
        timer1 = new Timer(10000);
        timer1.Elapsed += new ElapsedEventHandler(timer1_Elapsed);
    }

protected override void OnStart(string[] args)
    {
        EventLog.WriteEntry("Application", "Service started", EventLogEntryType.Information, 555);
        try
        {

            ipEndPoint = new IPEndPoint(IPAddress.Any, 8030);
            //Defines the kind of socket we want :TCP
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            //Bind the socket to the local end point(associate the socket to local end point)
            serverSocket.Bind(ipEndPoint);
            //listen for incoming connection attempt
            // Start listening, only allow 10 connection to queue at the same time
            serverSocket.Listen(10);
            timer1.Start();
        }
        catch (SocketException ex)
        {
            EventLog.WriteEntry("Application",  ex.ErrorCode + "-" +ex.Message, EventLogEntryType.Error, 555);
        }
        catch (Exception ex)
        {
            EventLog.WriteEntry("Application", ex.Message, EventLogEntryType.Error, 555);
        }
    }

    void timer1_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {

            // The program is suspended while waiting for an incoming connection.
            // This is a synchronous TCP application
            Socket handler = serverSocket.Accept();              
            byte[] fileDetails = new byte[1500];

            //Recieve the file details
            handler.Receive(fileDetails);              
            int fileNameLength = BitConverter.ToInt32(fileDetails, 0);
            string fileName = Encoding.ASCII.GetString(fileDetails, 4, fileNameLength);
            int fileLength = BitConverter.ToInt32(fileDetails, 4 + fileNameLength);  

            FileStream fs = new FileStream(@"C:\Demo\" + fileName, FileMode.Append, FileAccess.Write);
            int byteRead = 0;

            while (byteRead < fileLength)
            {
                byte[] data = new Byte[1500];
                //Recieve teh data and write to the file
                int r = handler.Receive(data);
                fs.Write(data, 0, r);
                byteRead += r;
            }

            fs.Close();

            EventLog.WriteEntry("Application", "File saved successfully", EventLogEntryType.SuccessAudit, 555);               
            EndPoint endPoint = (EndPoint)ipEndPoint;
            handler.Send(Encoding.ASCII.GetBytes("Done"));
            handler.Close();
        }
        catch (SocketException ex)
        {
            EventLog.WriteEntry("Application", ex.Message, EventLogEntryType.Error, 555);
        }
        catch (IOException ex)
        {
            EventLog.WriteEntry("Application", ex.Message, EventLogEntryType.Error, 555);
        }
        catch (Exception ex)
        {
            EventLog.WriteEntry("Application", ex.Message, EventLogEntryType.Error, 555);

        }
    }


    protected override void OnStop()
    {
        timer1.Stop();
    }

    protected override void OnPause()
    {
        timer1.Stop();
    }

    protected override void OnContinue()
    {
        timer1.Start();

    }
    protected override void OnShutdown()
    {
        timer1.Stop();
    }
}

Client Program Code

public partial class Form1 : Form
{
    Socket socketClient;
    IPEndPoint remoteEndPoint;
    public Form1()
    {
        InitializeComponent();

    }

    private void buttonX1_Click(object sender, EventArgs e)
    {
        try
        {
            //Code to connect to server by by specifing the IP and port of the server on 
            //which the server application is hosted
            socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //socketClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress,(int)1);

            //IP address of the machine where the server program is hosted
            IPAddress remoteIPAddress = IPAddress.Parse(txtXIPAddress.Text.Trim());

            //Specify the specific port no thart the server listens to accept the data
            int port = int.Parse(txtXPort.Text.Trim());
            remoteEndPoint = new IPEndPoint(remoteIPAddress, port);

            **//This two line causing the exception**
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9030);
            socketClient.Bind(endPoint);

            //Establish the connection to server
            socketClient.Connect(remoteEndPoint);

            MessageBox.Show("Connection established. Please select a  file to send.");
        }
        catch (SocketException ex)
        {
            MessageBox.Show(ex.ErrorCode.ToString() + "-" + ex.Message);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void btnXBrowse_Click(object sender, EventArgs e)
    {
        if (socketClient != null)
        {
            openFileDialog1.ShowDialog();
        }
        else
        {
            MessageBox.Show("Please connect to the server first");
        }

    }

    private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
    {

        txtXFile.Text = openFileDialog1.FileName;
    }

    private void btnXTransfer_Click(object sender, EventArgs e)
    {
        //Check if the socket is connected to the remote host 
        //otherwise prompt user to get connected to the server first
        if (socketClient != null && socketClient.Connected)
        {
            //If any file is selected then only proceed with transfer
            if (!openFileDialog1.FileName.Equals(string.Empty))
            {
                FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
                try
                {
                    //Get the filename
                    string filename = Path.GetFileName(openFileDialog1.FileName);

                    //Covert the file name in form of byte
                    byte[] fileNameByte = Encoding.ASCII.GetBytes(filename);

                    //4- to store the filename length(as int - 4bytes)
                    //8- to stote the file content length(as long take 8 bytes)
                    int totalLength = 4 + fileNameByte.Length + 8;

                    //Clientdata[] reprents the data to sent to the server 
                    //which represent the file details
                    byte[] clientData = new byte[totalLength];
                    byte[] fileNameLength = BitConverter.GetBytes(fileNameByte.Length);
                    byte[] fileContentLength = BitConverter.GetBytes(fs.Length);

                    //Copy all the data ClientData array
                    fileNameLength.CopyTo(clientData, 0);
                    fileNameByte.CopyTo(clientData, 4);
                    fileContentLength.CopyTo(clientData, 4 + fileNameByte.Length);

                    //Send the data to server
                    socketClient.Send(clientData);

                    int byteRead = 0;
                    int bytesToRead = (int)fs.Length;

                    while (bytesToRead > 0)
                    {
                        byte[] data = new Byte[1500];
                        byteRead = bytesToRead > 1500 ? 1500 : bytesToRead;
                        int n = fs.Read(data, 0, byteRead);

                        //Send the data to server
                        socketClient.Send(data);
                        bytesToRead -= n;
                    }

                    //Code block to get the success message from server
                    byte[] successmessage = new byte[4];
                    int msg = socketClient.Receive(successmessage);

                    if (Encoding.ASCII.GetString(successmessage).Equals("Done"))
                    {
                        MessageBox.Show("transfered the file successfully");
                        txtXFile.Text = string.Empty;
                        openFileDialog1.FileName = string.Empty;
                    }

                }

                catch (SocketException ex)
                {
                    MessageBox.Show(ex.ErrorCode + "-" + ex.Message);
                }
                catch (IOException ex)
                {
                    MessageBox.Show(ex.Message);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    fs.Close();
                    if (socketClient != null && socketClient.Connected)
                    {
                        socketClient.Shutdown(SocketShutdown.Both);
                        socketClient.Close(); ;
                    }
                }
            }
            else
            {
                MessageBox.Show("Please select afile to transfer.");
            }
        }
        else
        {
            MessageBox.Show("Please connect to the host.");
        }
    }
}

回答1:

Note: You don't have to bind the local end of the client's socket -- the framework and/or OS will bind to an ephemeral port automatically. In fact, if you bind the socket to 127.0.0.1, assuming connecting doesn't throw an exception about unreachable hosts, one of two things will happen (i'm not sure which):

  • The client will try and connect to the server, but since the local end is bound to the loopback interface's IP, it will send over that instead of over the network. -or-
  • The client will correctly route the packet out through the NIC, and the server gets it. The server replies "OK, let's get this connection set up" to the client...but since the client said its address was 127.0.0.1, that's where the server will be trying to connect. Using its own loopback interface, cause that's where 127.0.0.1 is routed to.

Either way, the packets get lost in one of the machines' loopback interfaces, and the client will never see a response.

If you must bind in the client, pick your real IP address, or use IPAddress.Any, like so:

var endPoint = new IPEndPoint(IPAddress.Any, 9030);

That'll bind to a given port but still let the OS choose the IP address. But 127.0.0.1 probably won't work.