Asynchronous Sockets/Threads?

coldfusion244

Well-known member
Joined
Nov 24, 2004
Messages
266
Location
Philadelphia
Hello everyone,

I am attempting to make a client/server program using sockets, but the program hangs on the Socket.AcceptConnection() line until there is a connection made. I was searching around and found some code on how to do it, but it used neither the AcceptConnection using a listener nor the read.ReadString(). I was wondering if anyone knows of some good tutorials or has some commented socket code laying around. MSDN was a waste of time, since I am new to network programming. I want to have multiple clients connected to the server at one time, and be able to send information back and forth. Not looking for many clients, max will probably be 50, if that.

I was using the following code:
[CS]
private void wfc()
{
TcpListener listener;
try
{
while(true)
{
listener = new TcpListener(50000);
listener.Start();
connection = listener.AcceptSocket();

clsClient CC = new clsClient(connection, this.t1);

listener.Stop();
listener = null;
}
}
catch(Exception e)
{
t1.Text = e.ToString();
}

}
[/CS]


Thanks,
-Cold
 
HJB, the examples I looked at are poorly commented. If you could make a small example of the asynchronous or have an example that is commented well handy I would greatly appreciate it :D
 
Code:
public void Asynchronous_wfc()
{
	//make a tcp socket
	Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
	//bind it to all nics on port 11000.
	socket.Bind(new IPEndPoint(IPAddress.Any, 11000));
	//listen for connections.
	socket.Listen(5);
	//method returns immediately but SomeoneConnected will be invoked
	//when someone connects.
	socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket);
}

private void SomeoneConnected(IAsyncResult result)
{
	//result.AsyncState stores the 2nd argument of BeginAccept
	//in this case, a socket, because I made it store a socket.
	Socket socket = (Socket) result.AsyncState;

	//you need to call end accept to get the connected socket.
	Socket remoteEnd = socket.EndAccept(result);

	//call begin accept again to get the next incoming connection.
	socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket);
}
Whats so bad about delegates?
 
Thanks HJB, the way you explained it was, well, the best ive seen! I am starting to understand it now. So basically I am going to have to do the same thing for reading and writing data... I would have to make all of those using the same argument list so that they would be asynchronous...
 
yes, theres more to know about asynchronous operations in the bcl. but thats the basic. Theres stuff like the waithandle.

e.x.:
Code:
IAsynchResult result = socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket);
//the WaitOne will not return until a connection attempt is receievd.
result.AsyncWaitHandle.WaitOne();
 
Still confuzzled

Ok Hjb, I attempted for two days now to get the receive and send to work, no such luck (I must be brain dead).

In the server portion I have this:
[CS]
private void SomeoneConnected(IAsyncResult result)
{
//result.AsyncState stores the 2nd argument of BeginAccept
//in this case, a socket, because I made it store a socket.
Socket socket = (Socket) result.AsyncState;

//you need to call end accept to get the connected socket.
Socket remoteEnd = socket.EndAccept(result);
t1.Text += "\r\nSomeone Connected!";
//call begin accept again to get the next incoming connection.

byte[] buffer = System.Text.Encoding.UTF8.GetBytes("");
socket.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None,new AsyncCallback(CheckPackets),socket);
socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket);

}
private void CheckPackets(IAsyncResult result)
{
byte[] buffer = System.Text.Encoding.UTF8.GetBytes("");
Socket socket = (Socket) result.AsyncState;
int dsocket = socket.EndReceive(result);
socket.Receive(buffer);
t1.Text+="\r\n" + System.Text.Encoding.UTF8.GetString(buffer);
socket.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None, new AsyncCallback(CheckPackets),socket);
}
[/CS]

In the client part I have:
[CS]
private void Connected(IAsyncResult result)
{
//result.AsyncState stores the 2nd argument of BeginAccept
//in this case, a socket, because I made it store a socket.
Socket socket = (Socket) result.AsyncState;

//you need to call end accept to get the connected socket.
socket.EndConnect(result);
label1.Text += "\r\nWe Connected!";
byte[] msg = System.Text.Encoding.UTF8.GetBytes("Test message!");
int i = socket.Send(msg);
Console.WriteLine("Sent " + i + " bytes of data.");
}
[/CS]

The client responds as sending 13 bytes of data, but in the server program I receive the error:
An unhandled exception of type System.InvalidOperationException occurred in system.dll

Additional information: AcceptCallback

What am I doing wrong?!
 
remoteEnd is what is connected to the "remote end", not socket.

Code:
private void SomeoneConnected(IAsyncResult result)
		{
			//result.AsyncState stores the 2nd argument of BeginAccept
			//in this case, a socket, because I made it store a socket.
			Socket socket = (Socket) result.AsyncState;

			//you need to call end accept to get the connected socket.
			Socket remoteEnd = socket.EndAccept(result);
			t1.Text += "\r\nSomeone Connected!";
			//call begin accept again to get the next incoming connection.

			byte[] buffer = System.Text.Encoding.UTF8.GetBytes("");
			remoteEnd.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None,new AsyncCallback(CheckPackets),socket);
			socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket);

		}
 
Ok, I can send data between the two programs, but it only sends it 1 byte at a time... Is there any way to send it all at once?
 
Last edited by a moderator:
HJB417 said:
I think you need to post reproduceable code.

HJB, I do appreciate all the time and posts you made! ;)

Screenshot - Click Here
Server Code:
[CS]
private void SomeoneConnected(IAsyncResult result)
{
//result.AsyncState stores the 2nd argument of BeginAccept
//in this case, a socket, because I made it store a socket.
Socket socket = (Socket) result.AsyncState;
//you need to call end accept to get the connected socket.
Socket remoteEnd = socket.EndAccept(result);
t1.Text += "\r\nSomeone Connected!";
//call begin accept again to get the next incoming connection.
byte[] buffer = System.Text.Encoding.UTF8.GetBytes("");
remoteEnd.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None,new AsyncCallback(CheckPackets),remoteEnd);
socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket);
}
private void CheckPackets(IAsyncResult result)
{
//byte[] buffer = System.Text.Encoding.UTF8.GetBytes("no");
Socket socket = (Socket) result.AsyncState;
int dsocket = socket.EndReceive(result);
if (dsocket<=0)
{
}
else
{
t1.Text+="\r\nReceived " + dsocket + " bytes of data." + " - " + System.Text.Encoding.UTF8.GetString(buffer);
}
socket.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None, new AsyncCallback(CheckPackets),socket);
}
[/CS]

Client code:
[CS]
/********************/
byte[] msg = System.Text.Encoding.UTF8.GetBytes("Test message!");
public Socket mysocket;

/********************/
private void Connected(IAsyncResult result)
{
//result.AsyncState stores the 2nd argument of BeginAccept
//in this case, a socket, because I made it store a socket.
Socket socket = (Socket) result.AsyncState;
//you need to call end accept to get the connected socket.
socket.EndConnect(result);
mysocket = socket;
label1.Text += "\r\nWe Connected!";
sendstuff(mysocket);
}

private void button2_Click(object sender, System.EventArgs e)
{
sendtuff(mysocket);
}

private void sendstuff(Socket socket)
{
socket.BeginSend(msg,0,msg.Length,System.Net.Sockets.SocketFlags.None,new AsyncCallback(sending),socket);
}

private void sending(IAsyncResult ar)
{
Socket socket = (Socket) ar.AsyncState;
int i = socket.EndSend(ar);
Console.WriteLine("Sent " + i + " Bytes.");
}
[/CS]
 
Code:
private void SomeoneConnected(IAsyncResult result)
{
	//result.AsyncState stores the 2nd argument of BeginAccept
	//in this case, a socket, because I made it store a socket.
	Socket socket = (Socket) result.AsyncState;
	//you need to call end accept to get the connected socket.
	Socket remoteEnd = socket.EndAccept(result);
	t1.Text += "\r\nSomeone Connected!";
	//call begin accept again to get the next incoming connection.
	byte[] buffer = new byte[65536];
	// instead of storing just the remote end
	// im going to store an array that contains the remote end and
	// the array the socket will write/store the received data.
	remoteEnd.BeginReceive(buffer, 0, buffer.Length, System.Net.Sockets.SocketFlags.None, new AsyncCallback(CheckPackets), new object[] {remoteEnd, buffer});
	socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket);
}
private static void CheckPackets(IAsyncResult result)
{
	int amtRecvd = socket.EndReceive(result);
	// I access the data array to get the that was array
	// created in SomeoneConnected(IAsyncResult).
	object[] info = (object[]) result.AsyncState;
	Socket remoteEnd = (Socket) info[0];
	byte[] buffer = (byte[]) info[1];
	if (amtRecvd == 0)
	{
		//if amtRecvd == 0, all data has been receieved and the connection has been closed
		try
		{
			remoteEnd.Shutdown(SocketShutdown.Both);
		}
		finally
		{
			remoteEnd.Close();
		}
	}
	else
	{
		t1.Text+="\r\nReceived " + amtRecvd + " bytes of data." + " - " + System.Text.Encoding.UTF8.GetString(buffer, 0, buffer.Length);
		byte[] buffer = new byte[65536];
		remoteEnd.BeginReceive(buffer, 0, buffer.Length, System.Net.Sockets.SocketFlags.None, new AsyncCallback(CheckPackets), new object[] {remoteEnd, buffer});
	}
}
 
Ok, everything works now! Thanks for all youre help HJB, I appreciate it very much! The last question I have is, that when I run the server everythign is fine, then when a user connects it instantly jumps to 99% processor usage and slows my whole system down. Any idea why?
 
I am so stupid.... I had the function sending blank messages. I didnt put the beginsend inside the braces! so whether or not information was there it sent itself in a constant never ending loop! wow, I think ive been staying up way too late... :p Thanks for everything again HJB, youre a huge asset to the community!


-THREAD RESOLVED-
 
Back
Top