Socket.Shutdown throws SocketException - c#

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.

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());
}
}

socket server listening all the time

The requirement is server socket should accept the client socket connection all the time (windows service application). Below is the code which works fine for several hours, but after sometime accept does not work at all. To keep the accept all the time, I also have thread which connects the server every 10 min. By this way I got to know that server socket has stopped after some time (several hours)
public void StartReceiveNotification()
{
if (!isStarted)
{
try
{
byte[] bytes = new Byte[1024];
var ips = Dns.GetHostAddresses(Dns.GetHostName());
var myAddress = ips.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);
assigningIp = myAddress;
server = new TcpListener(myAddress, 11001);
server.Start();
AcceptSockets();
isStarted = true;
}
catch (Exception ex)
{
logger.Error(ex);
}
}
}
private void AcceptSockets()
{
try
{
while (true)
{
var acceptedSocket = server.AcceptSocket();
var state = new StateObject { BufferSize = 6000, Socket = acceptedSocket };
acceptedSocket.BeginReceive(state.Buffer, 0, state.BufferSize, 0, this.ReadCallback, state);
acceptedSockets.Add(acceptedSocket);
}
}
catch (Exception ex)
{
logger.Error(ex);// no exception but stops accepting socket
}
}
internal ElapsedEventHandler SendKeepLiveCommand()// triggers every 10 min
{
try
{
if (assigningIp != null)
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(assigningIp, 11001);
socket.Send(ASCIIEncoding.ASCII.GetBytes("keepAlive"));
socket.Disconnect(false);
socket.Dispose();
}
}
catch (Exception ex)
{
logger.Error(ex);// get exception after several hours
}
return null;
}
issue was server had vpn connection and it was using that ip address. when vpn connection lost server stopped listening.

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)
{}
}

TCP Socket is not responding

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;

Send a message back to a list of clients at any given time with async sockets in C#

Ive got an async server set up, it works perfectly by connecting, receiving and sending back a message to the connecting client.
The server itself is a Game-World-Server (mmorpg style). When a user sends its position to where its located, I need to push this out to all the clients with a PlayerPositionNotice. I know I'm missing some basic stuff here, but when i try to save the StateObject that was created in the accept method, and use that socket to send back information to the player at any given time it fails because the socket is closed. =/ Don't know why this happens and would I've searched a couple of engines on this but came back empty.
This is how i created my server:
First off we have the global stuff:
public StateManager _stateManager = new StateManager();
public bool IsClosing = false;
private const int _port = 1025;
private IPHostEntry _localhost;
private IPEndPoint _endpoint;
private Socket _serverSocket;
private Thread _serverThread;
Second of we have the initialize stuff:
public void Start()
{
_serverThread = new Thread(Initialize);
_serverThread.Start();
}
/// <summary>
/// Main entry point for the server
/// </summary>
private void Initialize()
{
Console.WriteLine("Server Main Socket Thread Initialized.");
_localhost = Dns.GetHostEntry(Dns.GetHostName());
try
{
_endpoint = new IPEndPoint(_localhost.AddressList[0], _port);
_serverSocket = new Socket(_endpoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(_endpoint);
_serverSocket.Listen(100);
_serverSocket.BeginAccept(new AsyncCallback(acceptCallback), _serverSocket);
}
catch (ArgumentOutOfRangeException)
{
Console.WriteLine(" >> Port number " + _port + " would seem to be invalid, should be between 1024 and 65000");
}
catch (SocketException)
{
Console.WriteLine(" >> Could not create socket, check to make sure not duplicating port");
}
catch (Exception e)
{
Console.WriteLine(" >> Error occured while binding socket, IE:" + e.InnerException);
}
}
So far so good, i expect.. And now to the rest of the server class.
private void acceptCallback(IAsyncResult result)
{
Console.WriteLine("Connection Accepted");
StateObject state = null;
try
{
state = new StateObject
{
workSocket = ((Socket)result.AsyncState).EndAccept(result)
};
_stateManager.AddConnection(state);
state.workSocket.BeginReceive(state.buffer, 0, state.buffer.Length,
SocketFlags.None, new AsyncCallback(receiveCallback), state);
_serverSocket.BeginAccept(new AsyncCallback(acceptCallback), _serverSocket);
}
catch (SocketException)
{
_stateManager.RemoveConnection(state);
_serverSocket.BeginAccept(new AsyncCallback(acceptCallback), _serverSocket);
}
catch (Exception)
{
_stateManager.RemoveConnection(state);
_serverSocket.BeginAccept(new AsyncCallback(acceptCallback), _serverSocket);
}
}
private void receiveCallback(IAsyncResult result)
{
var state = (StateObject)result.AsyncState;
try
{
// Buffer and count bytes read
int bytesRead = state.workSocket.EndReceive(result);
if (!state.workSocket.Connected)
_stateManager.RemoveConnection(state);
if (bytesRead > 0)
{
// Parse the message to the protocol manager and return a reply
var replyingData = ProtocolManager.Parse(state.buffer);
if (replyingData != null)
Send(replyingData, state);
//Queue the next receive
state.workSocket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), state);
}
else
{
_stateManager.RemoveConnection(state);
}
}
catch (SocketException e)
{
_stateManager.RemoveConnection(state);
}
}
public bool Send(byte[] message, StateObject state)
{
Console.WriteLine("Sending " + message.Length + " bytes");
if (state != null && state.workSocket.Connected)
{
lock (state.workSocket)
{
//we use a blocking mode send, no async on the outgoing
//since this is primarily a multithreaded application, shouldn't cause problems to send in blocking mode
state.workSocket.Send(message, message.Length, SocketFlags.None);
}
}
else return false;
return true;
}
The stateManager contains a list of StateObject.. Below you can see how i build them.
STATE MANAGER:
public class StateManager
{
private List<StateObject> _connections = new List<StateObject>();
public void AddConnection(StateObject so)
{
lock (_connections)
{
_connections.Add(so);
}
}
public void RemoveConnection(StateObject so)
{
if (so.workSocket != null)
{
so.workSocket.Close();
lock (_connections)
{
_connections.Remove(so);
}
}
}
}
STATE OBJECT
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
My problem here is that whenever anybody in this list sends something i want to send back a notice to alot of other clients. How and where can i implement this? Anybody that can kick me in the right direction? =)
This code seem to be correct and I don't know why you get "socket is closed" error, but there is another problem: in Send(byte[] message, StateObject state) method, because you call this when receiving from user and send received data back to that user.(not to all other users to notice them)
As you said, if you need to send new location to all other users:
Call this method instead of your Send(byte[] message, StateObject state), when received new location.
public void NoticeAllusers(byte []buffer,StateObject state)
{
foreach(StateObject obj in _stateManager._connections)
{
if (obj != state)
{
obj.workSocket.BeginSend(buffer,<parameters you>...., new AsyncCallback(OnSend) state.workSocket);
}
}
}
public void OnSend(IAsyncResult ar)
{
try
{
Socket sock = (Socket)ar.AsyncState;
sock.EndSend(ar);
}
catch { }
}
I hope it will help a little :)

Categories