Asynchronous client / server c# problem with second communication - c#

I´m struggling with problem that after first success full connection with sockets I can establish second without errors. What to do ? I have give there both application so you can try help me troubleshoot that problem. Thanks you very much guys!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace AsynchronousClientLearning
{
class Program
{
public class ObjectState
{
public const int BufferSize = 256;
public Socket wSocket { get; set; } = null;
public byte[] Buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
public class AsyncSocketClient
{
private const int Port = 4343;
private static ManualResetEvent connectComplete = new ManualResetEvent(false);
private static ManualResetEvent sendCompleted = new ManualResetEvent(false);
private static ManualResetEvent receiveCompleted = new ManualResetEvent(false);
private static string response = String.Empty;
public static void StartClient()
{
try
{
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ip = ipHost.AddressList[0];
IPEndPoint remoteEndPoint = new IPEndPoint(ip, Port);
Socket client = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(remoteEndPoint, new AsyncCallback(ConnectionCallback) , client);
Send(client, "this socket message<EOF>");
sendCompleted.WaitOne();
Receive(client);
receiveCompleted.WaitOne();
Console.WriteLine($"Response received {response}");
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static void Receive(Socket client)
{
try
{
ObjectState state = new ObjectState();
state.wSocket = client;
client.BeginReceive(state.Buffer,0,ObjectState.BufferSize,0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
ObjectState state = (ObjectState)ar.AsyncState;
var client = state.wSocket;
int byteRead = client.EndReceive(ar);
if(byteRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.Buffer, 0, byteRead));
client.BeginReceive(state.Buffer, 0, ObjectState.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
if(state.sb.Length > 1)
{
response = state.sb.ToString();
}
receiveCompleted.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
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 byteSent = client.EndSend(ar);
Console.WriteLine($"send: {byteSent} bytes to server");
sendCompleted.Set();
client.DisconnectAsync();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
private static void ConnectionCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
Console.Write($"Socket connection : {client.RemoteEndPoint.ToString()}");
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
static void Main(string[] args)
{
Console.WriteLine("Press any key to contine");
Console.ReadLine();
AsyncSocketClient.StartClient();
Console.ReadLine();
}
}
}
Server console application
that should be taking care about cca 10 clients so thread for everyone is not solution
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace AsynchronousServerLearning
{
class Program
{ public class ObjectState
{
public Socket wSocket = null;
public const int bufferSize = 1024;
public byte[] buffer = new byte[bufferSize];
public StringBuilder sb = new StringBuilder();
}
public class AsyncSocketListener
{
public static ManualResetEvent allCompleted = new ManualResetEvent(false);
public static void StartListener()
{
byte[] bytes = new byte[1024];
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ip = ipHost.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ip, 4343);
Socket listener = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while(true)
{
allCompleted.Reset();
Console.WriteLine("waiting for incoming connections......");
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
allCompleted.WaitOne();
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
Console.WriteLine("Press enter to continue");
Console.ReadLine();
}
private static void AcceptCallback(IAsyncResult ar)
{
allCompleted.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
ObjectState state = new ObjectState();
state.wSocket = handler;
handler.BeginReceive(state.buffer, 0, ObjectState.bufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
private static void ReadCallback(IAsyncResult ar)
{
string content = String.Empty;
ObjectState state = (ObjectState)ar.AsyncState;
Socket handler = state.wSocket;
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>", StringComparison.Ordinal) > -1)
{
Console.WriteLine($"Read: {content.Length} bytes from \n socket Data: {content}");
Send(handler,content);
}
else
{
handler.BeginReceive(state.buffer, 0, ObjectState.bufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, string content)
{
byte[] byteData = Encoding.ASCII.GetBytes(content);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
int byteSent = handler.EndSend(ar);
Console.WriteLine($"Sent {byteSent} to client");
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch( Exception e)
{
Console.WriteLine(e);
}
}
}
static void Main(string[] args)
{
Console.WriteLine("Press any key to continue");
Console.ReadLine();
AsyncSocketListener.StartListener();
Console.ReadLine();
}
}
}
Log from console:
Press any key to continue
Socket connection : [fe80::3d32:e16b:6438:ad43%8]:4343send: 24 bytes to server
Response received this socket message<EOF>
send: 24 bytes to server
Response received this socket message<EOF>
Socket connection : [fe80::3d32:e16b:6438:ad43%8]:4343System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult, SocketError& errorCode)
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
at AsynchronousClientLearning.Program.AsyncSocketClient.ReceiveCallback(IAsyncResult ar) in C:\Users\Z660659\source\repos\AsynchronousClientLearning\AsynchronousClientLearning\Program.cs:line 82
...when I try that:
static void Main(string[] args)
{
Console.WriteLine("Press any key to contine");
Console.ReadLine();
AsyncSocketClient.StartClient();
Console.ReadLine();
AsyncSocketClient.StartClient();
Console.ReadLine();
}

I have been looking for answear like 2 hours since I struggle. Now I came with solution that solver the error. With reseting manualReserEvents. If you found something better please let me know.
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
ObjectState state = (ObjectState)ar.AsyncState;
var client = state.wSocket;
int byteRead = client.EndReceive(ar);
if(byteRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.Buffer, 0, byteRead));
client.BeginReceive(state.Buffer, 0, ObjectState.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
if(state.sb.Length > 1)
{
response = state.sb.ToString();
}
receiveCompleted.Set();
connectComplete.Reset();
receiveCompleted.Reset();
sendCompleted.Reset();
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}

Related

TCP socket timeout

I wrote C# program that server sends data from Server to Client only.
Problem is that time between it sends data is changable ( max 5min)
and that causes sometimes connection to timeout.
When I send data every 3sec then none of them timeouts.
But if message send after 5min then there is problem on Client to recieve it.
I made timeout feature that both Client and Server has. After timeout every reconnects:
public class TimerControl
{
private System.Timers.Timer timeoutTimer = null;
public void initTimeout(int timeMS, System.Timers.ElapsedEventHandler funct)
{
timeoutTimer = new System.Timers.Timer();
timeoutTimer.Interval = timeMS; //MS
timeoutTimer.Elapsed += funct;
timeoutTimer.AutoReset = true;
setTimeoutTimer(false);
}
public void setTimeoutTimer(bool state)
{
if (timeoutTimer != null)
{
timeoutTimer.Stop();
timeoutTimer.Enabled = state;
if (state) timeoutTimer.Start();
}
}
public void resetTimeoutTimer()
{
if (timeoutTimer != null && timeoutTimer.Enabled)
{
timeoutTimer.Stop();
timeoutTimer.Start();
}
}
}
that has not solved the trouble.
What should I do to make it work correct and not timeout after some time?
Server:
public class TCPserver :TCPunit
{
private int TIMEOUT_MS = 5000;
Socket serverListener = null;
Queue<string> dataQueued = null;
bool isConnectedForced = false;
public TCPserver()
{
dataQueued = new Queue<string>();
initTimeout(TIMEOUT_MS, reconnect);
}
public void sendDataToClient(string message)
{
dataQueued.Enqueue(message + Environment.NewLine);
if(isConnectedForced) startListening();
if (dataQueued.Count > 0) setTimeoutTimer(true);
}
public bool connect(string adress)
{
this.thisUnitAdress = adress;
isConnectedForced = true;
loopedConnect();
startListening();
return true;
}
public bool disconnect()
{
isConnectedForced = false;
loopedDisconnect();
return true;
}
private bool loopedConnect()
{
try
{
IPAddress ipAddress = IPAddress.Parse(this.thisUnitAdress);
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
if (serverListener != null) loopedDisconnect();
serverListener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
serverListener.Bind(localEndPoint);
Console.WriteLine("SERVER connected to: " + this.thisUnitAdress + " port : " + port.ToString());
return true;
}
catch (Exception ex)
{
Console.WriteLine("!!! SERVER connect");
setTimeoutTimer(true);
return false;
}
}
private bool loopedDisconnect()
{
setTimeoutTimer(false);
if (serverListener != null)
{
if (serverListener.Connected) serverListener.Shutdown(SocketShutdown.Both);
serverListener.Close();
Console.WriteLine("SERVER CLOSED!");
serverListener = null;
}
return true;
}
private void reconnect(Object source, System.Timers.ElapsedEventArgs e)
{
if (isConnectedForced)
{
Console.WriteLine("SERVER RECONNECT!!!");
loopedDisconnect();
loopedConnect();
if (dataQueued.Count > 0) setTimeoutTimer(true);
else setTimeoutTimer(false);
}
else
{
setTimeoutTimer(false);
}
}
private void startListening()
{
try
{
serverListener.Listen(100);
Console.WriteLine("SERVER Waiting for a connection...");
serverListener.BeginAccept(new AsyncCallback(AcceptCallback), serverListener);
setTimeoutTimer(true);
}
catch (Exception ex)
{
Console.WriteLine("!!! SERVER sendingLOOP");
setTimeoutTimer(true);
}
}
private void AcceptCallback(IAsyncResult ar)
{
try
{
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
//HERE SEND
while (dataQueued.Count > 0)
{
string data = dataQueued.Dequeue();
byte[] byteData = Encoding.ASCII.GetBytes(data);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
//handler.Shutdown(SocketShutdown.Both);
//handler.Close();
setTimeoutTimer(false);
}
catch (Exception ex)
{
Console.WriteLine("!!! SERVER AcceptCallback");
setTimeoutTimer(true);
}
}
private void SendCallback(IAsyncResult ar)
{
try
{
((Socket)ar.AsyncState).EndSend(ar);
}
catch(Exception ex)
{
Console.WriteLine("!!! SERVER SendCallback");
setTimeoutTimer(true);
}
}
}
Client:
public class TCPclient : TCPunit
{
private int TIMEOUT_MS = 5000;
Socket client;
IPEndPoint remoteEP;
bool isConnecting = false;
bool isRecieving = false; // TELS IF PROGRAM SHOULD LOOK FOR SERVER ALL TIME
Action<string> afterRecieveAction = null ; // To print to GUI
public TCPclient()
{
initTimeout(TIMEOUT_MS, reconnect);
}
public void assignAfterRecieveAction(Action<string> action)
{
this.afterRecieveAction = action;
}
public bool connect(string adress)
{
thisUnitAdress = adress;
loopedConnect();
return true;
}
public bool disconnect()
{
isRecieving = false;
isConnecting = false;
loopedDisconnect();
return true;
}
private bool loopedConnect()
{
IPAddress ipAddress = IPAddress.Parse(this.thisUnitAdress);
remoteEP = new IPEndPoint(ipAddress, port);
client = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
setTimeoutTimer(true);
isRecieving = true;
StartClientListening();
return true;
}
private bool loopedDisconnect()
{
if (client != null)
{
if (client.Connected) client.Shutdown(SocketShutdown.Both);
client.Close();
Console.WriteLine("CLIENT CLOSED!");
client = null;
}
return true;
}
private void reconnect(Object source, System.Timers.ElapsedEventArgs e)
{
if (isRecieving)
{
Console.WriteLine("CLIENT RECONNECT!!!");
if (isConnecting) loopedDisconnect();
isRecieving = true;
loopedConnect();
}
}
private void StartClientListening()
{
try
{
if (isRecieving)
{
client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback) , client);
isConnecting = true;
Console.WriteLine("CLIENT listens to: " + thisUnitAdress + " port : " + port.ToString());
}
}
catch (System.Net.Sockets.SocketException ex)
{
Console.WriteLine("CLIENT StartClientListening");
}
catch (Exception ex)
{
Console.WriteLine("!!! CLIENT StartClientListening2");
if (isRecieving) setTimeoutTimer(true);
}
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
client.EndConnect(ar);
Console.WriteLine("CLIENT connected to {0}", client.RemoteEndPoint.ToString());
StateObject state = new StateObject();
state.workSocket = client;
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); ;
}
catch (Exception e)
{
Console.WriteLine("!!! CLIENT ConnectCallback");
if (isRecieving) setTimeoutTimer(true);
}
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
String response = Encoding.ASCII.GetString(state.buffer);
if (afterRecieveAction != null) afterRecieveAction(response);
resetTimeoutTimer();
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
}
catch(System.Net.Sockets.SocketException ex)
{
Console.WriteLine("!!! CLIENT ReceiveCallback");
if (isRecieving) setTimeoutTimer(true);
}
catch(Exception ex)
{
Console.WriteLine("!!! CLIENT ReceiveCallback2");
if (isRecieving) setTimeoutTimer(true);
}
}
}
How to make async Server-Client to work without timeouts?
Best regards,
Chris
You should use socket_set_option to parameter this

How to implement Socket server that accept more message

I want to send at real time some data from Android application to server.
So I'm building a simple socket Server in c# like this:
class Program
{
private Socket listener;
static void Main(string[] args)
{
Program p = new Program();
p.socketServer();
}
public void socketServer()
{
int MAXBUFFER = 1024;
Console.WriteLine("SOCKET STARTED");
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Any, 8080));
listener.Listen(10);
while (true)
{
Console.WriteLine("WAITING CONNECTION");
Socket socket = listener.Accept();
string receivedMessage = string.Empty;
while (true)
{
byte[] receivedBytes = new byte[MAXBUFFER];
int numBytes = socket.Receive(receivedBytes);
receivedMessage += Encoding.ASCII.GetString(receivedBytes, 0, numBytes);
if (receivedMessage.IndexOf("\n") > -1)
{
Console.WriteLine("MESSAGE FROM CLIENT: {0}", receivedMessage);
//break;
}
}
Console.WriteLine("MESSAGE FROM CLIENT: {0}", receivedMessage);
string replyMessage = "MESSAGE RECEIVED";
byte[] replyBytes = Encoding.ASCII.GetBytes(replyMessage);
}
}
public void shutdownServer()
{
listener.Shutdown(SocketShutdown.Both);
listener.Close();
}
}
And I'm building this class to send data from Android application:
public class TcpClient {
public static final String SERVER_IP = "192.168.110.50"; // computer IP address
public static final int SERVER_PORT = 8080;
private String mServerMessage;
private OnMessageReceived mMessageListener = null;
private boolean mRun = false;
private PrintWriter mBufferOut;
private BufferedReader mBufferIn;
private Socket socket;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TcpClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
*
* #param message text entered by client
*/
public void sendMessage(String message) {
socket.isConnected();
if (mBufferOut != null /*&& !mBufferOut.checkError()*/) {
mBufferOut.println(message);
}
}
/**
* Close the connection and release the members
*/
public void stopClient() {
Log.i("Debug", "stopClient");
// send mesage that we are closing the connection
//sendMessage(Constants.CLOSED_CONNECTION + "Kazy");
mRun = false;
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mMessageListener = null;
mBufferIn = null;
mBufferOut = null;
mServerMessage = null;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
//create a socket to make the connection with the server
socket = new Socket(SERVER_IP, SERVER_PORT);
//socket.connect(socket.getRemoteSocketAddress());
socket.isConnected();
try {
Log.i("Debug", "inside try catch");
mBufferOut = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
And in the MainActivity I use this code:
tcpClient = new TcpClient(new TcpClient.OnMessageReceived() {
#Override
//here the messageReceived method is implemented
public void messageReceived(String message) {
//this method calls the onProgressUpdate
//publishProgress(message);
}
});
tcpClient.run();
After connect to server i user this code to send message:
for(int i=0; i<10; i++){
tcpClient.sendMessage("test " + i);
}
The problem is that only the first message arrive to the server. I think that the problem is on the socket server that lost the connection with the client.

Response from asynchronous server to asynchronous client is NULL in C#

I have asynchronous communication between client and server. When the client receives a response from the server (ReceiveCallback), the response is stored in public static string response in my NetworkHandler class. I am trying to use this field in my GameHandler class, but it says that response is empty.
I am sure that my buffer in NetworkHandler is not empty, because I checked it.
I think it happens because NetworkHandler.response is called before the response gets a value, but I am not sure and I don't know how to solve it...
See the comments in the code for more explanation...
Please take a look at this image to see the null value in GameHandler: http://i.imgur.com/BPVDlhf.png And here to see the correct value in NetworkHandler: http://i.imgur.com/vfY2IuD.png
class NetworkHandler
{
public static string response = String.Empty;
private static void ReceiveCallback(IAsyncResult AR)
{
Socket remote = (Socket)AR.AsyncState;
int received = remote.EndReceive(AR);
byte[] dataBuffer = new byte[received];
Array.Copy(_buffer, dataBuffer, received);
string serverData = Encoding.ASCII.GetString(dataBuffer);
response = serverData;
}
private static void SendCallback(IAsyncResult AR)
{
Socket remote = (Socket)AR.AsyncState;
int sent = remote.EndSend(AR);
remote.BeginReceive(_buffer, 0, _size, SocketFlags.None, new AsyncCallback(ReceiveCallback), remote);
}
public static void sendData(string data)
{
byte[] message = Encoding.ASCII.GetBytes(data);
_client.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(SendCallback), _client);
}
private static void ConnectCallback(IAsyncResult AR)
{
_client = (Socket)AR.AsyncState;
try
{
_client.EndConnect(AR);
_client.BeginReceive(_buffer, 0, _size, SocketFlags.None, new AsyncCallback(ReceiveCallback), _client);
}
catch (SocketException e)
{
Console.WriteLine(e.ToString());
}
}
}
class GameHandler
{
public void StartGame()
{
// SEND DATA USING BEGINSEND()
SendData("<sg>");
// THIS VALUE IS NULL!!! :(
_response = NetworkHandler.response;
// SO CODE INSIDE IF IS NOT EXECUTED :(
if (_response != null)
{
// If you are the drawer.
if (_response.Substring(0, 5) == "<dra>")
etc.........
}
}
public void SendData(string data)
{
NetworkHandler.sendData(data);
}
}

Multiple Clients in Client Server app in C#

using resources at http://www.developerfusion.com i came up with the following server code. It works well for single client. How can i make it for multiple clients. I tried adding array and different instances of the beiginreceive but was unable to. The server code:
class Program
{
public static AsyncCallback pfnWorkerCallBack;
public static Socket m_socListener;
public static Socket m_socWorker;
static void Main(string[] args)
{
try
{
//create the listening socket...
m_socListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, 8221);
//bind to local IP Address...
m_socListener.Bind(ipLocal);
Console.WriteLine("UCManager Started");
//start listening...
m_socListener.Listen(4);
// create the call back for any client connections...
m_socListener.BeginAccept(new AsyncCallback(OnClientConnect), null);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
public static void OnClientConnect(IAsyncResult asyn)
{
try
{
m_socWorker = m_socListener.EndAccept(asyn);
WaitForData(m_socWorker);
}
catch (Exception se)
{
Console.WriteLine(se.Message);
}
}
public class CSocketPacket
{
public System.Net.Sockets.Socket thisSocket;
public byte[] dataBuffer = new byte[1];
}
public static void WaitForData(System.Net.Sockets.Socket soc)
{
try
{
if (pfnWorkerCallBack == null)
{
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
}
CSocketPacket theSocPkt = new CSocketPacket();
theSocPkt.thisSocket = soc;
// now start to listen for any data...
soc.BeginReceive(theSocPkt.dataBuffer, 0, theSocPkt.dataBuffer.Length, SocketFlags.None, pfnWorkerCallBack, theSocPkt);
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}
public static void OnDataReceived(IAsyncResult asyn)
{
try
{
CSocketPacket theSockId = (CSocketPacket)asyn.AsyncState;
//end receive...
int iRx = 0;
iRx = theSockId.thisSocket.EndReceive(asyn);
char[] chars = new char[iRx + 1];
Decoder d = Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
String szData = new String(chars);
Console.WriteLine(szData);
int code = Convert.ToInt32(szData);
WaitForData(m_socWorker);
}
catch (Exception se)
{
Console.WriteLine(se.Message);
}
}
}
}
EDIT: Ok i did something on the lines of Async TCP Server for multiple Clients.
public static void OnClientConnect(IAsyncResult asyn)
{
try
{
Socket m_socWorkerInstance = m_socListener.EndAccept(asyn);
clientSocketList.Add(m_socWorkerInstance);
WaitForData(m_socWorkerInstance);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}
public static void WaitForData(System.Net.Sockets.Socket soc)
{
try
{
if (pfnWorkerCallBack == null)
{
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
}
CSocketPacket theSocPkt = new CSocketPacket();
theSocPkt.thisSocket = soc;
// now start to listen for any data...
soc.BeginReceive(theSocPkt.dataBuffer, 0, theSocPkt.dataBuffer.Length, SocketFlags.None, pfnWorkerCallBack, theSocPkt);
m_socListener.BeginAccept(new AsyncCallback(OnClientConnect), null);
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}
Now i am able to connect two clients but not able to communicate ...I am unable to send message from server to client...any suggestions...also should i have different read functions for both clients if i connect with two client???
You call BeginAccept only once, so after one client has been accepted, your server won't accept any new connections. You should call BeginAccept again after accepting a connection.
Ok i was able to solve it using Async TCP Server for multiple Clients:
public static void OnClientConnect(IAsyncResult asyn)
{
try
{
Socket m_socWorkerInstance = m_socListener.EndAccept(asyn);
clientSocketList.Add(m_socWorkerInstance);
WaitForData(m_socWorkerInstance);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}
public static void WaitForData(System.Net.Sockets.Socket soc)
{
try
{
if (pfnWorkerCallBack == null)
{
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
}
CSocketPacket theSocPkt = new CSocketPacket();
theSocPkt.thisSocket = soc;
// now start to listen for any data...
soc.BeginReceive(theSocPkt.dataBuffer, 0, theSocPkt.dataBuffer.Length, SocketFlags.None, pfnWorkerCallBack, theSocPkt);
m_socListener.BeginAccept(new AsyncCallback(OnClientConnect), null);
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}

Out of memory exception on server, but most troubling; events not being called unless I debug

I have this very weird error. Basically, as soon as I add the line of code Connections.Add(handler); my program goes haywire. I'm also getting the error:
System.OutOfMemoryException: Exception of type
'System.OutOfMemoryException' was thrown. at
System.Threading.ExecutionContext.CreateCopy() at
System.Net.ContextAwareResult.CaptureOrComplete(ExecutionContext&
cachedContext, Boolean returnContext)
What happens is, when I add this code, connections are still being accepted, but nothing is being logged on my log richtextbox control. This is very weird, and I have no idea whats going on. However, removing that Connections.Add(handler) line in my accept event solves all problems. But I need to keep track of sockets somehow so I can implement pinging to keep them alive
Here is my code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Concurrent;
namespace SpybotServer
{
public partial class Server : Form
{
public void log(String text)
{
logs.InvokeEx(a => a.Text += (text +Environment.NewLine));
}
public Server()
{
InitializeComponent();
}
private void Server_Load(object sender, EventArgs e)
{
Thread serverThread = new Thread(delegate()
{
Listener.StartListening(9001);
});
serverThread.Start();
heartbeat.Start();
}
private void Server_FormClosed(object sender, FormClosedEventArgs e)
{
Listener.looping = false;
}
private void heartbeat_Tick(object sender, EventArgs e)
{
Listener.heartbeat();
}
}
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
public class Listener
{
public static Boolean looping = true;
private static List<Socket> Connections = new List<Socket>();
public static void heartbeat()
{
Program.MainForm.log("Sending ping...");
}
public static void StartListening(int port)
{
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 9001);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Program.MainForm.log("Listening on port " + port);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while (looping)
{
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
}
}
catch (Exception e)
{
Program.MainForm.log(e.ToString());
}
}
public static void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state.workSocket = handler;
IPEndPoint ip = handler.RemoteEndPoint as IPEndPoint;
Program.MainForm.log("Accepted connection from " + ip.Address);
//Connections.Add(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.workSocket;
try
{
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_END>#!") > -1)
{
Program.MainForm.log(content);
}
else
{
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}*/
}
}
catch (Exception e)
{
Program.MainForm.log(e.ToString());
}
}
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)
{
Socket handler = (Socket)ar.AsyncState;
try
{
int bytesSent = handler.EndSend(ar);
if (bytesSent <= 0)
{
Program.MainForm.log("Socket has been closed.");
}
}
catch (Exception e)
{
Program.MainForm.log(e.ToString());
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
}
}
InvokeEx:
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace SpybotServer
{
static class ISynchronizeInvokeExtensions
{
public static void InvokeEx<T>(this T #this, Action<T> action) where T : ISynchronizeInvoke
{
if (#this.InvokeRequired)
{
#this.Invoke(action, new object[] { #this });
}
else
{
action(#this);
}
}
}
}
Since this callback:
public static void AcceptCallback(IAsyncResult ar)
is inside this loop:
while (looping)
{
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
}
I'm more than 90% certain that you are adding the same Socket to the Connections list over and over and just growing the size of the list at an alarming rate. Change the add to this:
if (Connections.Contains(handler))
{
Connections.Add(handler);
}
Michael is on the right track, but not with the right solution.
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
Is (unlike Accept) not going to block and weird things are going to happen if you call it this way. Instead take your BeginAccept out of a loop and call it again from AcceptCallback so that you can accept a new connection after you have accepted a first.

Categories

Resources