TCP Socket is not responding - c#

I am developing TCP Client/Server application using C# socket programming. Sometimes, I encounter a very strange problem as the server (windows service) is running on port (8089) but it is not listening to any client request, and when I test the port with a port scanner it told me that the port is not responding! here is my server code :
First,
private void MainThread() {
byte[] bytes = new Byte[1024];
IPEndPoint localEndPoint = new IPEndPoint(0, this.port);
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
try {
listener.Bind(localEndPoint);
listener.Listen(100);
while (active) {
mainDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
while (active)
if (mainDone.WaitOne(100, true))
break;
}
listener.Close();
} catch (Exception e) {
if (OnError != null)
OnError(this, e.ToString());
LogManager.LogError(e, "TCPSimpleServer MainThread");
}
Then,
private void AcceptCallback(IAsyncResult ar) {
Socket handler = null;
try
{
mainDone.Set();
Socket listener = (Socket)ar.AsyncState;
handler = listener.EndAccept(ar);
if (OnConnect != null)
OnConnect(this, handler);
StateObject state = new StateObject();
state.workSocket = handler;
state.endPoint = (IPEndPoint)handler.RemoteEndPoint;
stateObjectDictionary.Add(state, state.workSocket);
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
catch (ObjectDisposedException)
{
// Connection closed by client
if (OnDisconnect != null)
OnDisconnect(this, (IPEndPoint)handler.RemoteEndPoint);
return;
}
catch (Exception ex)
{
LogManager.LogError(ex, "TCPSimpleServer AcceptCallback");
return;
}
and Finally,
private void ReadCallback(IAsyncResult ar) {
try
{
String content = String.Empty;
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int bytesRead = 0;
try
{
bytesRead = handler.EndReceive(ar);
}
catch (Exception ex)
{
// Connection closed by client
if (OnDisconnect != null)
OnDisconnect(this, state.endPoint);
handler.Close();
return;
}
if (bytesRead > 0)
{
string data = Encoding.Default.GetString(state.buffer, 0, bytesRead);
if (OnDataAvailable != null)
OnDataAvailable(this, handler, data);
try
{
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
catch (Exception e)
{
if (OnError != null)
OnError(this, e.Message);
LogManager.LogError(e, "TCPSimpleServer ReadCallback");
handler.Close();
}
}
else
{
// Connection closed by peer
if (OnDisconnect != null)
OnDisconnect(this, state.endPoint);
}
}
catch (Exception ex)
{
LogManager.LogError(ex, "TCPSimpleServer ReadCallback");
}
}
I think the problem is in the last method ReadCallback() if problen occured in EndReceive() method the socket (handler) never release the port. any help please?

Could it be, that a client can block the server at:
while (active)
if (mainDone.WaitOne(100, true))
break;

Related

C# socket client server messages swap

I have setup a client server chat system. That will have to work on different computers. At the moment I am testing and so both client and server are on my localhost.
At the moment I focus on the client reception (with a 8192 byte buffer) for it is that the problem resides.
And the problem is that when issue a command with very short text (here 123):
Server SHORT_COMMAND 123% ---> Client SHORT_COMMAND 123%
but when I issue a very long command (24k) each single batch does not arrive in the correct order
E.g. imagine a very long text 111.....11112222....2222333....33334444....4444
LONG_COMMAND 111....3333% is therefore automatically cut into
LONG_COMMAND 111....1111
2222....2222
3333...3333
4444...4444%
and sent in that order
what is wrong is the reception and what might happen is to receive
LONG_COMMAND 111....1111
2222....2222
4444...4444%
3333...3333
or it might get mixed with other short commands like
LONG_COMMAND 111....1111
2222....2222
SHORT_COMMAND 123%
3333...3333
4444...4444%
Take into account that some messages can be sent very quickly one after the other.
Thank you for ANY help
Patrick
Client code
I start the client with the following routine. In my case I pass -1
public static bool StartClient(string strIpAddress, string strPort)
{
// Connect to a remote device.
try
{
if (strIpAddress.Trim() == "-1")
strIpAddress = GetLocalIPAddress();
IPAddress ipAddress = IPAddress.Parse(strIpAddress);
int port = int.Parse(strPort);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { NoDelay = true };
socketClient.BeginConnect(remoteEP, new AsyncCallback(ConnectClientCallback), socketClient);
OnNotification_Client?.Invoke(eSocketOperation.CONNECT, "Client connected to " + strIpAddress + " port=" + strPort, eSocketOperationResultType.SUCCESS);
ReceiveClient();
return true;
}
catch (Exception e)
{
MessageBox.Show("StartClient exc:" + e.ToString());
return false;
}
}
then
private static void ConnectClientCallback(IAsyncResult ar)
{
try
{
socketClient = (Socket)ar.AsyncState;
socketClient.EndConnect(ar);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
The following part is the reception with:
public static void ReceiveClient()
{
try
{
StateObject state = new StateObject();
state.workSocket = socketClient;
socketClient.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback_Client), state);
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "ReceiveClient", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
finally
private static void ReceiveCallback_Client(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
if (!client.Connected)
return;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
string message = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
if (message == null)
OnNotification_Client?.Invoke(eSocketOperationResultType.ERROR, "Received null message from server", eSocketOperationResultType.ERROR);
else
{
strReceivedMessageClient += message;
if (strReceivedMessageClient.EndsWith(StateObject.CONFIRMATION.ToString()))
{
...
Server Code
The server is started with
public static void StartServer(string _strPort)
{
Serializers.Logger.WriteLog("StartServer");
StrPort = _strPort;
// Data buffer for incoming data.
byte[] bytes = new Byte[BufferSize];
IPAddress ipAddress = IPAddress.Parse(GetLocalIPAddress());
int port = int.Parse(_strPort);
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
if (listener == null)
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
OnNotification_Server?.Invoke("Waiting for a connection on " + ipAddress.ToString());
listener.BeginAccept(new AsyncCallback(AcceptCallbackServer), listener);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
Accept
public static void AcceptCallbackServer(IAsyncResult ar)
{
if (listener == null)
return;
listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback_Server), state);
}
and last but not least the send:
public static void SendFromServerToClient(object command, String data, eSocketOperationResultType sort)
{
string strMessage; ;
strMessage = command.ToString() + '|' + data + '|' + sort + "%";
byte[] byteData = Encoding.ASCII.GetBytes(strMessage);
try
{
if (socketServer != null)
socketServer.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), socketServer);
}
catch (Exception exc)
{
}
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}

C# Client - Server Socket Disconnect Handling

I've got a client - server code going on at the moment while working on my thesis.
And I can spawn a connection and send data, but as soon as the client disconnects and tries to reconnect everything goes sideways and I can't seem to figure out why. Too many exceptions are being thrown and I just have no idea where to start catching them all.
What am doing wrong or not doing that isn't allowing nether client nor server to handle disconnections properly ?!
This is my ServerSide Code:
using System;
using System.Net;
using System.Net.Sockets;
namespace Server.Networking
{
public class ServerSocket
{
private Socket _socket;
Byte[] _buffer = new byte[61144];
public ServerSocket()
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
public void Bind(int port)
{
_socket.Bind(new IPEndPoint(IPAddress.Any, port));
}
public void Listener(int backlog)
{
_socket.Listen(backlog);
}
public void Accept()
{
_socket.BeginAccept(AcceptedCallback, null);
}
private void AcceptedCallback(IAsyncResult result)
{
try
{
Socket clientSocket = _socket.EndAccept(result);
if (clientSocket.Connected)
{
Console.WriteLine("Client has connected!");
_buffer = new byte[61144];
clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, clientSocket);
Accept();
}
else
{
Console.WriteLine("Client hasn't connected!");
return;
}
}catch(SocketException ex)
{
Console.WriteLine(ex.Message);
close(clientSocket);
}
}
private void ReceivedCallback(IAsyncResult result)
{
try
{
Socket clientSocket = result.AsyncState as Socket;
SocketError SE;
int bufferSize = clientSocket.EndReceive(result, out SE);
if (bufferSize > 0)
{
if (SE == SocketError.Success)
{
byte[] packet = new byte[bufferSize];
Array.Copy(_buffer, packet, packet.Length);
Console.WriteLine("Handling packet from IP:" + clientSocket.RemoteEndPoint.ToString());
//Handle packet stuff here.
PacketHandler.Handle(packet, clientSocket);
_buffer = new byte[61144];
clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, clientSocket);
}
else
{
close(clientSocket);
}
}
else
{
Console.WriteLine("Probably received bad data.");
close(clientSocket);
}
}
catch (SocketException ex)
{
Console.WriteLine(ex.Message);
close(clientSocket);
}
}
public void close(Socket sock)
{
Console.WriteLine("Closing socket for IP:" + sock.RemoteEndPoint.ToString() + " and releasing resources.");
sock.Dispose();
sock.Close();
}
}
}
And this is my ClientSide Code:
using System;
using System.Net;
using System.Linq;
using System.Net.Sockets;
using Client.Networking.Packets;
using System.Net.NetworkInformation;
using Client.Networking.Packets.Request;
namespace Client.Networking
{
public class ClientSocket
{
private Socket _socket;
private byte[] _buffer;
public delegate void RaiseConnect(object source, TextArgs e);
public static event EventHandler Disconnected;
private static void RaiseDisconnect()
{
EventHandler handler = Disconnected;
if(handler !=null)
{
handler(null, EventArgs.Empty);
}
}
public ClientSocket()
{
udpbroadcast.Connect += new RaiseConnect(OnConnectRaise);
}
public string machineIP()
{
return Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString();
}
private void OnConnectRaise(object sender, TextArgs e)
{
CheckRegisteredRequest computer_name = new CheckRegisteredRequest(Environment.MachineName.ToString() + "," + machineIP());
Connect(e.Message, 6556);
Send(computer_name.Data);
}
public void Connect(string ipAddress, int port)
{
string ip = ipAddress;
int porT = port;
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result =_socket.BeginConnect(new IPEndPoint(IPAddress.Parse(ip), port), ConnectCallback, null);
bool success = result.AsyncWaitHandle.WaitOne(5000, true);
if(!success)
{
_socket.Close();
Console.WriteLine("Failed to connect to server. Trying again.");
Connect(ip, port);
}
}
private void ConnectCallback(IAsyncResult result)
{
try {
if (_socket.Connected)
{
Console.WriteLine("Connected to the server!");
_buffer = new byte[61144];
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, null);
}
else
{
Console.WriteLine("Could not connect.");
Close(_socket);
}
}
catch(SocketException ex)
{
Console.WriteLine("ClientSocket ConnectCallback - "+ex.Message);
Close(_socket);
}
}
private void ReceivedCallback(IAsyncResult result)
{
try
{
SocketError SE;
int buflength = _socket.EndReceive(result, out SE);
if (buflength > 0)
{
if(SE == SocketError.Success)
{
byte[] packet = new byte[buflength];
Array.Copy(_buffer, packet, packet.Length);
//Handle the Package
PacketHandler.Handle(packet, _socket);
_buffer = new byte[61144];
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, null);
}
else
{
Close(_socket);
}
}
else
{
Close(_socket);
}
}
catch (Exception ex)
{
Console.WriteLine("ClientSocket ReceivedCallback - " + ex.Message);
Close(_socket);
}
}
public void Send(byte[] data)
{
byte[] send = new byte[data.Length];
send = data;
if( _socket.Connected)
{
_socket.Send(data);
}
else
{
Console.WriteLine("Not connected yet!");
Close(_socket);
}
}
public bool connectionStatus()
{
return _socket.Connected;
}
public static void Close(Socket sock)
{
Console.WriteLine("Closing the socket and releasing resources.");
sock.Dispose();
sock.Close();
RaiseDisconnect();
}
}
}
Two things I can think of. The documentation on Socket recommends calling Shutdown() first, before Close().
Also, you cannot reuse a socket object. So make sure you're using a new Socket object before trying a new connection, either by _socket = new Socket(), or by using a totally new ServerSocket/ClientSocket.
I managed to get it working with the following code. Within the server code, I initiate the BeginReceive witihn the AcceptedCallback in the following way:
clientSocket.BeginReceive(new byte[] {0}, 0, 0, 0, ReceivedCallback, clientSocket);
Then within the ReceivedCallback, i do BeginReceive differently like this:
clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, clientSocket);
While being bothered by the exceptions, it seems that I've skipped checking what I'm receiving in the initial connection.
At the client code, within the ConnectCallback method i do begin receive the other way around:
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, null);
And within the ReceivedCallback method I did BeginReceive the in reverse:
_socket.BeginReceive(new byte[] { 0 }, 0, 0, 0, ReceivedCallback, null);
After three hours of debugging, it makes sense in a way to me.
The server spawns a new socket object every time it Accepts a connection, in order to avoid threading. So on the Server side at the AcceptedCallback method, the initial _socket.BeginReceive should call the ReceivedCallback method via an empty byte array to only triggers it. Then within the ReceivedCallback you do BeginReceive with an array customized to the length that's been received by the socket. Whereas at Client side, it's reversed.
This is my server side code:
private Socket _socket;
Byte[] _buffer = new byte[61144];
public ServerSocket()
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
public void Bind(int port)
{
_socket.Bind(new IPEndPoint(IPAddress.Any, port));
}
public void Listener(int backlog)
{
_socket.Listen(backlog);
}
public void Accept()
{
_socket.BeginAccept(AcceptedCallback, null);
}
private void AcceptedCallback(IAsyncResult result)
{
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
Console.WriteLine("We accepted a connection.");
clientSocket = _socket.EndAccept(result);
if (clientSocket.Connected)
{
Console.WriteLine("Client has connected!");
_buffer = new byte[61144];
//clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, clientSocket);
clientSocket.BeginReceive(new byte[] {0}, 0, 0, 0, ReceivedCallback, clientSocket);
Accept();
}
else
{
Console.WriteLine("Client hasn't connected!");
Accept();
}
}
catch (Exception ex)
{
Console.WriteLine("Socket was probably forcefully closed." + ex.Message);
Console.WriteLine("Continue accepting other connections.");
clientSocket.Close();
Accept();
}
}
private void ReceivedCallback(IAsyncResult result)
{
Socket clientSocket = result.AsyncState as Socket;
SocketError ER;
try
{
int bufferSize = clientSocket.EndReceive(result, out ER);
if (ER == SocketError.Success)
{
byte[] packet = new byte[bufferSize];
Array.Copy(_buffer, packet, packet.Length);
Console.WriteLine("Handling packet from IP:" + clientSocket.RemoteEndPoint.ToString());
//Handle packet stuff here.
PacketHandler.Handle(packet, clientSocket);
_buffer = new byte[61144];
clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, clientSocket);
//clientSocket.BeginReceive(new byte[] { 0 }, 0, 0, 0, ReceivedCallback, clientSocket);
}
else
{
Console.WriteLine("No bytes received, we're closing the connection.");
clientSocket.Close();
}
}catch(SocketException ex)
{
Console.WriteLine("We caught a socket exception:" + ex.Message);
clientSocket.Close();
}
}
And this is my Client side code:
private Socket _socket;
private CheckRegisteredRequest computer_name;
private bool isClosed;
private byte[] _buffer;
public delegate void RaiseConnect(object source, TextArgs e);
public static event EventHandler Disconnected;
private static void RaiseDisconnect()
{
EventHandler handler = Disconnected;
if (handler != null)
{
handler(null, EventArgs.Empty);
}
}
public ClientSocket()
{
isClosed = true;
udpbroadcast.Connect += new RaiseConnect(OnConnectRaise);
computer_name = new CheckRegisteredRequest(Environment.MachineName.ToString() + "," + machineIP());
}
private void OnConnectRaise(object sender, TextArgs e)
{
if(!isClosed)
{
_socket.Close();
Connect(e.Message, 6556);
}
else
{
Connect(e.Message, 6556);
}
}
public void Connect(string ipAddress, int port)
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.BeginConnect(new IPEndPoint(IPAddress.Parse(ipAddress), port), ConnectCallback, null);
isClosed = false;
/*IAsyncResult result =
bool success = result.AsyncWaitHandle.WaitOne(5000, true);
if (!success)
{
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
Console.WriteLine("Failed to connect to server. Trying again.");
RaiseDisconnect();
}*/
}
private void ConnectCallback(IAsyncResult result)
{
try
{
if(_socket.Connected)
{
_socket.EndConnect(result);
Console.WriteLine("We initiated a connection to the server.");
Console.WriteLine("Connected to the server!");
Send(computer_name.Data);
_buffer = new byte[61144];
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, null);
}
else
{
Console.WriteLine("Could not connect.");
if(!isClosed)
{
_socket.Close();
isClosed = true;
RaiseDisconnect();
}
else
{
isClosed = true;
RaiseDisconnect();
}
}
}
catch (SocketException ex)
{
Console.WriteLine("ConnectCallback Exception Caught.");
Console.WriteLine("Shutting down and closing socket for reusal.");
if (!isClosed)
{
_socket.Close();
isClosed = true;
RaiseDisconnect();
}
else
{
isClosed = true;
RaiseDisconnect();
}
}
}
private void ReceivedCallback(IAsyncResult result)
{
try
{
SocketError SE;
int buflength = _socket.EndReceive(result, out SE);
if (SE == SocketError.Success)
{
byte[] packet = new byte[buflength];
Array.Copy(_buffer, packet, packet.Length);
//Handle the Package
PacketHandler.Handle(packet, _socket);
_buffer = new byte[61144];
//_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, null);
_socket.BeginReceive(new byte[] { 0 }, 0, 0, 0, ReceivedCallback, null);
}
else
{
Console.WriteLine("No bytes received, we're closing the connection.");
if (!isClosed)
{
_socket.Close();
isClosed = true;
RaiseDisconnect();
}
else
{
isClosed = true;
RaiseDisconnect();
}
}
}
catch (Exception ex)
{
Console.WriteLine("ReceivedCallback Exception Caught.");
Console.WriteLine("Shutting down and closing socket for reusal.");
if (!isClosed)
{
_socket.Close();
isClosed = true;
RaiseDisconnect();
}
else
{
isClosed = true;
RaiseDisconnect();
}
}
}
public void Send(byte[] data)
{
byte[] send = new byte[data.Length];
send = data;
if (_socket.Connected)
{
_socket.Send(data);
}
else
{
Console.WriteLine("We're not connected yet!");
if (!isClosed)
{
_socket.Close();
isClosed = true;
RaiseDisconnect();
}
else
{
isClosed = true;
RaiseDisconnect();
}
}
}
public bool connectionStatus()
{
return _socket.Connected;
}
public string machineIP()
{
return Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString();
}

asynch socket listener receiving data very late for some clients

I am making a server socket in c# with async method. Here is the code I am using....
http://msdn.microsoft.com/en-us/library/fx6588te%28v=vs.110%29.aspx
Currently there are more than 200 clients connected at a time (can be more than 1000 at a time). Connected clients are just sending data (no need to send back messages by server).
Problem: Socket is receiving data often late (1-10 hrs late) from some clients.
What should be changed in the code to resolve the issue.
My actual code is below...
public static ManualResetEvent allDone = new ManualResetEvent(false);
public static void StartListening()
{
IPEndPoint ipEndPoint = new IPEndPoint(Dns.Resolve(Dns.GetHostName()).AddressList[0], GlobalVariable.ListenPort);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind((EndPoint)ipEndPoint);
listener.Listen(GlobalVariable.MaxConnectionBacklog);
while (true)
{
allDone.Reset();
//Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
allDone.WaitOne();
}
}
catch (Exception ex)
{
}
}
public static void AcceptCallback(IAsyncResult ar)
{
try
{
allDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = ((Socket)ar.AsyncState).EndAccept(ar);
StateObject stateObject = new StateObject();
stateObject.workSocket = handler;
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
catch (Exception ex)
{
}
}
public static void ReadCallback(IAsyncResult ar)
{
string content="";
try
{
string str = string.Empty;
StateObject stateObject = (StateObject)ar.AsyncState;
Socket handler = stateObject.workSocket;
int count = handler.EndReceive(ar);
if (count <= 0)
return;
stateObject.sb.Append(Encoding.ASCII.GetString(stateObject.buffer, 0, count));
stateObject.sb.Clear();
if (content.IndexOf("<EOF>") > -1)
{
// processing data with db insertion.
}
else
{
handler.BeginReceive(stateObject.buffer, 0,stateObject.buffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), stateObject);
}
}
catch (Exception ex)
{}
}

Socket.Shutdown throws SocketException

I'm trying to implement async sockets for my project. Here's the code
public void Start(int listeningPort)
{
var ipHostInfo = Dns.Resolve(Dns.GetHostName());
var ipAddress = ipHostInfo.AddressList[0];
var localEndPoint = new IPEndPoint(ipAddress, listeningPort);
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_listener.Bind(localEndPoint);
_listener.Listen(3000);
Started = true;
Task.Factory.StartNew(() =>
{
while (Started)
{
allDone.Reset();
_listener.BeginAccept(AcceptCallback, _listener);
allDone.WaitOne();
}
});
}
public void Stop()
{
Started = false;
_listener.Shutdown(SocketShutdown.Both); //<-- throws SocketException
_listener.Close(2000);
_listener = null;
}
public void Kick(IClient client)
{
try
{
Clients.Remove(client);
client.Socket.Shutdown(SocketShutdown.Both);
client.Socket.Close();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
private void AcceptCallback(IAsyncResult ar)
{
Socket handler = null;
try
{
allDone.Set();
var listener = (Socket) ar.AsyncState;
handler = listener.EndAccept(ar);
var client = new Client(this, handler);
Clients.Add(client);
var state = new StateObject();
state.Socket = handler;
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
var client = ClientBySocket(handler);
if(handler != null && client != null) Kick(client);
}
}
private void ReadCallback(IAsyncResult ar)
{
Socket handler = null;
try
{
var state = (StateObject) ar.AsyncState;
handler = state.Socket;
var bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
if (Received != null)
{
var buff = new byte[bytesRead];
if (buff[0] == 0)
{
Stop();
}
return;
Array.Copy(state.Buffer, buff, bytesRead);
Debug.WriteLine(Encoding.UTF8.GetString(buff));
try
{
Received(this, new ReceiveArgs(buff));
}
catch(Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
var client = ClientBySocket(handler);
if (handler != null && client != null) Kick(client);
}
}
but everytime I call Stop (which in turn, calls shutdown) (no matter clients are connected or not), Socket.Shutdown throws SocketException with message
Additional information: A request to send or receive data was
disallowed because the socket is not connected and (when sending on a
datagram socket using a sendto call) no address was supplied
I'm really stuck here. Anyone knows what I'm doing wrong?
Your listening socket is not connected. I think the message says this quite well. Everytime you accept a connection you get a new socket that is independent. The original socket is never connected to anything.
Just don't call Shutdown on it.
Btw, your Accept loop is using async IO, then waiting for it to complete. That makes no sense. Use the synchronous version.

Client receiving packet only on close

Basically I made two C# applications, a client and a server. The client connects to the server (via sockets), then sends a packet containing some text, and the server should reply.
My problem is: the server sends (or the client receives) the response packet only when it closes (ALT+F4). I'd like some help. I'll copypaste below the source code for both the projects.
Client:
public class StateObject
{
public Socket skt = null;
public const int BufferSize = 256;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousClient
{
private const int port = 11000;
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false);
private static String response = String.Empty;
public static string command;
public static Socket client;
public static void StartClient()
{
try
{
IPHostEntry ipHostInfo = Dns.GetHostEntry(IPAddress.Parse("127.0.0.1"));
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
while (true)
{
command = Console.ReadLine();
if (command == "exit")
{
Console.WriteLine("Terminating...");
client.Shutdown(SocketShutdown.Both);
client.Close();
Environment.Exit(0);
}
else
{
Send(client, command + "<EOF>");
sendDone.WaitOne();
Receive(client);
receiveDone.WaitOne();
Console.WriteLine("Response received : {0}", ProcessResponse(response));
client.Shutdown(SocketShutdown.Both);
client.Close();
}
//Console.CancelKeyPress += (sender, e) =>
//{
// Console.WriteLine("Terminating...");
// client.Shutdown(SocketShutdown.Both);
// client.Close();
// Environment.Exit(0);
//};
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
static public string ProcessResponse(string pkt)
{
string response = null;
response = pkt.Replace("<EOF>","");
return response;
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client)
{
try
{
StateObject state = new StateObject();
state.skt = client;
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.skt;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartClient();
return 0;
}
Server:
public class Program
{
public class StateObject
{
public Socket skt = null;
public const int buffersize = 1024;
public byte[] buffer = new byte[buffersize];
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousSocketListener
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
public AsynchronousSocketListener() { }
public static Socket handler;
public static void StartListening()
{
byte[] bytes = new Byte[1024];
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
allDone.Reset();
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar)
{
allDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state.skt = handler;
handler.BeginReceive(state.buffer, 0, StateObject.buffersize, 0, new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.skt;
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, ProcessResponse(content));
Send(handler, content);
}
else
{
handler.BeginReceive(state.buffer, 0, StateObject.buffersize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, String data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
static public string ProcessResponse(String pkt)
{
string response = null;
response = pkt.Replace("<EOF>", "");
return response;
}
}
public static void Main(string[] args)
{
AsynchronousSocketListener.StartListening();
}
}
In your Client receive callback:
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.skt;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
You won't ever drop down into the else block unless the socket is explicitly closed (or there is some kind of other error in the connection). Therefore receiveDone never gets set and your main loop is simply stuck waiting for a "response".
If you want to process a "complete message" when it comes in, then check for your <EOF> value after you append the current string to your buffer like this:
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// it's not a "response" unless it's terminated with "<EOF>" right?
response = state.sb.ToString();
if (response.IndexOf("<EOF>") != -1)
{
state.sb.Clear();
receiveDone.Set();
}
else
{
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
}
else
{
if (state.sb.Length > 1)
{
response = state.sb.ToString(); // this is a partial response, not terminated with "<EOF>"
}
receiveDone.Set();
}
Note that response mechanism being used is extremely limited as it would fail for multiple messages coming in at the same time like: Hello<EOF> World!<EOF> It would treat those two messages as one long message. (I realize your example is only sending one "message".)
You're almost certainly going to have to deal with that scenario in any real world application that sends "control" messages in addition to "content" messages. To handle that you'd look for <EOF> using IndexOf() and extract the text up to that point and process that "complete message". Afterwards you'd keep looping as long as <EOF> is still found to process the other pending messages. You'd also have to REMOVE those processed complete messages from the StringBuilder in such a way that any remaining values after the <EOF> are left in place so that when partial messages come in the new data can be appended to the existing data. This is because your data can also be split up when it is sent, resulting in multiple "chunks" of data being received even though it is logically one "complete message" when you sent it. So one send with Complete Message<EOF> could result in one or more receives such as Comp followed by lete Message<EOF>. Your code has to be able to deal with these realities of TCP communication...

Categories