Hey guys I'm having problems with some Asynchronous socketing that I have been trying. ...I don't want to post my entire code but I will try to put in what is necessary.
My problem is that I can't continue to send messages to my Server class and have them echo the message back to the Client more than ONE TIME.
I have gleaned some of my coding techniques through other examples so bear with my probable misinterpretation of their usage. :)
Here is the class that handles ANY data that is sent back to the Client:
public class Client
{
...
...
...
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
...
....
....
private void ListenForData()
{
while (true)
{
receiveDone.Reset();
ReceiveData(clientSocket);
receiveDone.WaitOne();
}
}
public void ReceiveData(Socket client)
{
try
{
StateObject stateObj = new StateObject();
stateObj.WorkSocket = client;
client.BeginReceive(stateObj.testBuff, SocketFlags.None,
new AsyncCallback(ReceiveDataCallback),
stateObj);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
private void ReceiveDataCallback(IAsyncResult result)
{
StateObject stateObj = (StateObject)result.AsyncState;
Socket handler = (Socket)stateObj.WorkSocket;
int bytesRead = handler.EndReceive(result);
string data = String.Empty;
if (bytesRead > 0)
{
IList<ArraySegment<byte>> infoList = stateObj.testBuff;
//A user defined class that contains a method I write which seperates the data into its respective components of message and userID.
byte[][] temp = ConversionClass.generateByteArrays(infoList[0].Array);
byte[] msgBuff = temp[0];
byte[] clientBuff = temp[1];
string msg = Encoding.ASCII.GetString(msgBuff);
string Id = Encoding.ASCII.GetString(clientBuff);
string date = DateTime.Now.ToString();
data = date + ' ' + clientID + ": " + msg;
stateObj.StringBuffer.Append(data);
/*stateObj.StringBuffer.Append(Encoding.ASCII.GetString(
stateObj.Buffer, 0, bytesRead));*/
if (data.IndexOf(EOM) > -1)
{
data = data.Trim(EOM.ToCharArray());
notifyMessageHandlerUsers(data);
//ReceiveData(clientSocket);
//I tried just unblocking the receiveDone thread but it didn't work so i tried just recalling the receive method. That also does not work after the first message is received.
}
else
{
handler.BeginReceive(stateObj.testBuff, SocketFlags.None,
new AsyncCallback(ReceiveDataCallback),
stateObj);
}
}
//supposidly this would unblock the thread that is currently running the ListenForData() methed. But it appears to not be working.
receiveDone.Set();
}
....
....
....
}
just a few notes about this method. It is the callback method that is assigned when data is passed back thorugh the socket connection to the server. I chose to use an IList for the parameters rather than just a plain old buffer because I wanted to seperate the data ... date, clientID, message, etc... lol, but it just combines them all into one buffer anyways once they are received by the Server. So I use a 'End of Unit' (31) character to signify the seperation of data.
Example: (I know you can't just concatenate byte arrays like this but I'm in a hurry so bear with it ;) )
string message = "hello";
string id = "matt";
byte[] byteArray = Encoding.ASCII.GetBytes(message) + 31 + Encoding.ASCII.GetBytes(id);
As you can see, when actually done correctly ;) there would be signified diffences between the message and the id.
Now just for clarification, the ListenForData() method is called after a connection is made with the server and it gets through the loop to the call ReceiveData() and then the thread is blocked.
How do I get the thread to resume running after a message is finished transmitting?
thanks !
p.s
in case anyone decides to ask I'll just post my StateObject class as well: it's rough right now because I'm still in the learning process so I don't want to clean up code till I'm sure of what I'm doing.
public class StateObject
{
public const int BufferSize = 1024; // Size of receive buffer.
private Socket workSocket; // Client socket.
public IList<ArraySegment<byte>> testBuff;
private byte[] buffer; // Receive buffer.
private StringBuilder stringBuffer;//Received data String.
private string id; // Host or conversation ID
private string timeStamp;
public StateObject()
{
testBuff = new List<ArraySegment<byte>>(2);
byte[] msgBuff = new byte[BufferSize];
byte[] clientID = new byte[16];
testBuff.Add(new ArraySegment<byte>(msgBuff));
testBuff.Add(new ArraySegment<byte>(clientID));
buffer = new byte[BufferSize];
stringBuffer = new StringBuilder();
id = String.Empty;
timeStamp = DateTime.Now.ToString();
}
//nd all corresponding Properties for attributes
..
...
...
...
}