Same Code, But Different Results in Windows Form and in Windows Service During Socket Connection

老子叫甜甜 提交于 2019-12-11 11:45:50

问题


I have a code which acts as a Socket listener (server side), and I implement it in the WinForms and in the Windows Service. Everything inside is the same, except that I changed the implementation of Windows Service OnStart and OnStop to buttonStart_Click and buttonStop_Click in WinForm.

Here is the code for WinForm:

private void buttonStart_Click(object sender, EventArgs e) { //should start to listen to the TCP/IP         
    if (serverHandler.IsMyTargetPortBusy())
        return;
    try {
        serverHandler.InitiateMySocket(); //basically start the socket listening internally
        logInput("Start");
    } catch { //Fail to do the job. At this moment, don't do anything
        //TODO put something for logging
        return;
    }
}

private void buttonStop_Click(object sender, EventArgs e) {
    this.Close(); //Need to change to application exit for the service          
}

Then, I tested the code by attempting to connect by using a Generic TCP-IP Client application. And the first step is to connect to the Socket listener (server side)

When the connection is to be made, the client would enter a method with the following code:

  clientHandler.InitiateSocket(myServerIpv4Address, serverPortNo);
  if (clientHandler.IsConnected()) {
      //Do something
  } else {
      //Do something, note the error message below
    logBox.WriteTimedLog("Connecting attempt through TCP/IP is failed! Timeout Occurs!\n", Color.Red);
  }

In the clientHandler.InitiateConnect we have

//something else
clientSocket.LoopConnect(5, 3); //In the InitiateConnect

And for the clientSocket instance which is of type Socket, I have the following methods:

//LoopConnect
public void LoopConnect(int noOfRetry, int attemptPeriodInSeconds) {
    int attempts = 0;
    while (!this.Connected && attempts < noOfRetry) {
        try {
            ++attempts;
            IAsyncResult result = this.BeginConnect(ipv4Address, portNo, endConnect, null);
            result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(attemptPeriodInSeconds));
            Thread.Sleep(attemptPeriodInSeconds * 1000);
        } catch (Exception e) {
             //Something else
        }
        //Something else
    }
    //Something else
}

//endConnect
private void endConnect(IAsyncResult result) {
  try {
    this.EndConnect(result);
    if (this.Connected) {
      this.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), this);
    } else if (ErrorMessageHandler != null) //ErrorMessageHandler is an event handler
      ErrorMessageHandler("End of connection attempt, fail to connect...\n");
  } catch (Exception e) {
      //Something
  }
}

//Receive callback
const int MAX_RECEIVE_ATTEMPT = 10;
int receiveAttempt = 0;
private void receiveCallback(IAsyncResult result) {
  System.Net.Sockets.Socket socket = null;
  try {
    socket = (System.Net.Sockets.Socket)result.AsyncState;  
    if (socket.Connected) {
      int received = socket.EndReceive(result);
      if (received > 0) {
        receiveAttempt = 0;
        byte[] data = new byte[received];
        Buffer.BlockCopy(buffer, 0, data, 0, data.Length); 
        //something else
        socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket);
      } else if (receiveAttempt < MAX_RECEIVE_ATTEMPT) {
        ++receiveAttempt;
        socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket);
      } else { //completely fails!
        if (ErrorMessageHandler != null) //Note the error message
          ErrorMessageHandler("receiveCallback is failed!\n"); 
        receiveAttempt = 0;
        this.Close();
      }
    }
  } catch (Exception e) { 
      //Something else
  }
}

And in the clientHandler.IsConnected(), it is nothing but

public bool IsConnected() {
  return clientSocket != null && clientSocket.Connected;
}

To my surprise, I got different results from the WinForms compared to from Windows Service when connecting to the server.

This is my client message when the server is in WinForm:

[2016-01-13 12:41:23.831 UTC] Attempting TCP/IP connection...
[2016-01-13 12:41:23.831 UTC] Attempting to connect to the TCP/IP server...
[2016-01-13 12:41:26.857 UTC] Connected to IP address: 127.0.0.1, Port: 5123
[2016-01-13 12:41:26.857 UTC] Connecting attempt through TCP/IP is successful!
[2016-01-13 12:41:26.889 UTC] Connection attempt: 1
[2016-01-13 12:41:26.889 UTC] Connection attempt is successful!

This is my client message when the server is in Windows Service:

[2016-01-13 12:42:14.464 UTC] Attempting TCP/IP connection...
[2016-01-13 12:42:14.480 UTC] Attempting to connect to the TCP/IP server...
[2016-01-13 12:42:17.558 UTC] Connecting attempt through TCP/IP is failed! Timeout Occurs!
[2016-01-13 12:42:17.558 UTC] receiveCallback is failed!
[2016-01-13 12:42:20.245 UTC] Attempting TCP/IP connection...
[2016-01-13 12:42:20.245 UTC] Attempting to connect to the TCP/IP server...
[2016-01-13 12:42:23.261 UTC] Connected to IP address: 127.0.0.1, Port: 5123
[2016-01-13 12:42:23.261 UTC] Connecting attempt through TCP/IP is successful!
[2016-01-13 12:42:23.277 UTC] Connection attempt: 1
[2016-01-13 12:42:23.277 UTC] Connection attempt is successful!

Problem

In WinForms application, the connection works at the first attempt. But in the Windows Service I always failed at the first attempt and has to repeat the second time to get connected, although internally, the first failure means I have already repeated the connection attempt 10 times (take a look on receiveCallback code).

Now, because of the error messages that the client produces,

[2016-01-13 12:42:17.558 UTC] Connecting attempt through TCP/IP is failed! Timeout Occurs!
[2016-01-13 12:42:17.558 UTC] receiveCallback is failed!

I managed to narrow down the code part which causes the error:

The first one comes from here

  clientHandler.InitiateSocket(myServerIpv4Address, serverPortNo);
  if (clientHandler.IsConnected()) {
      //Do something
  } else {
      //Do something, note the error message below
    logBox.WriteTimedLog("Connecting attempt through TCP/IP is failed! Timeout Occurs!\n", Color.Red);
  }

And the second one from here:

//Receive callback
const int MAX_RECEIVE_ATTEMPT = 10;
int receiveAttempt = 0;
private void receiveCallback(IAsyncResult result) {
  System.Net.Sockets.Socket socket = null;
  try {
    socket = (System.Net.Sockets.Socket)result.AsyncState;  
    if (socket.Connected) {
      int received = socket.EndReceive(result);
      if (received > 0) {
        receiveAttempt = 0;
        byte[] data = new byte[received];
        Buffer.BlockCopy(buffer, 0, data, 0, data.Length); 
        //something else
        socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket);
      } else if (receiveAttempt < MAX_RECEIVE_ATTEMPT) {
        ++receiveAttempt;
        socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket);
      } else { //completely fails!
        if (ErrorMessageHandler != null) //Note the error message
          ErrorMessageHandler("receiveCallback is failed!\n"); 
        receiveAttempt = 0;
        this.Close();
      }
    }
  } catch (Exception e) { 
      //Something else
  }
}

Sadly, though I can narrow down the source of error, I cannot explain why and consequently do not know how to fix it. Can anybody tell why?

Additional info:

  • At first, I thought this could be because the service has not been started long enough. But even I have waited the service for few minutes, the result is the same. And that proves me wrong.

来源:https://stackoverflow.com/questions/34767669/same-code-but-different-results-in-windows-form-and-in-windows-service-during-s

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!