问题
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