Skip to main content
gamedev.net
🔒 Locked

[.net] async sockets question (server)

Started by majek Mar 20, 2009 at 2:29 PM 1 replies 750+ views
Original Post
majek
majek
Hello, I'm a newb when it comes to System.Net.Sockets but I understand the basics. I'm working on a game that allows multiple clients to connect to a server. I'll try to keep my question as short as possible but it requires some explanation... When a client connects, the server adds the socket to an ArrayList. Then it passes the index of the client (ArrayList.Count - 1) to the WaitForData method. This way the first client that connects has an index of 0, the second has an index of 1, etc. When the server receives data, it creates a state object that stores the socket, the data, and the index of the client that sent the data. When a client disconnects, the server removes the socket from the ArrayList and relays back to all the other clients that someone disconnected. My problem is that the index is stored in a state object rather than a local variable so theres no way to iterate through each client and decrement the index if someone disconnects. For example: 3 clients connect to the server with the indeces 0 1 and 2. If client1 disconnects, client2 should become client1 and client0 should stay the same. What really happens: If client1 disconnects, the other clients still have the index 0 and 2, resulting in a OutOfRangeException. Is there any way I can accomplish this? Any help would be greatly appreciated, thanks.
private void ClientConnected(IAsyncResult ar)
{
	try
	{
		Socket clientSocket = serverSocket.EndAccept(ar);
		SocketList.Add(clientSocket);
		onClientConnect(SocketList.Count - 1);
		WaitForData(clientSocket, SocketList.Count - 1);
		serverSocket.BeginAccept(new AsyncCallback(ClientConnected), null);
	}
	catch (SocketException se)
		MessageBox.Show(se.Message);
}
	
private void WaitForData(Socket clientSocket, int clientIndex)
{
	try
	{
		if (WaitForDataCallback == null) WaitForDataCallback = new AsyncCallback(DataReceived);
		ServerPacket serverPacket = new ServerPacket(clientSocket, clientIndex);
		clientSocket.BeginReceive(serverPacket.DataBuffer, 0, serverPacket.DataBuffer.Length, SocketFlags.None, WaitForDataCallback, serverPacket);
	}
	catch (SocketException se)
		MessageBox.Show(se.Message);
}
	
private void DataReceived(IAsyncResult ar)
{
	ServerPacket serverPacket = (ServerPacket)ar.AsyncState;

	try
	{
		int iRx = serverPacket.CurrentSocket.EndReceive(ar);
		char[] chars = new char[iRx + 1];
		Decoder d = Encoding.UTF8.GetDecoder();
		int charLength = d.GetChars(serverPacket.DataBuffer, 0, iRx, chars, 0);
		string szData = new string(chars);
		onDataReceived(szData, serverPacket.ClientIndex);
		WaitForData(serverPacket.CurrentSocket, serverPacket.ClientIndex);
	}
	catch (SocketException se)
	{
		if (se.ErrorCode == 10054) // Connection reset by peer
			onClientDisconnect(serverPacket.ClientIndex);
		else MessageBox.Show(se.Message);
	}
}
	
public class ServerPacket
{
	public Socket CurrentSocket;
	public int ClientIndex;
	public byte[] DataBuffer;

	public ServerPacket(Socket currentSocket, int clientIndex)
	{
		CurrentSocket = currentSocket;
		ClientIndex = clientIndex;
		DataBuffer = new byte[1024];
	}

}
[Edited by - majek on March 20, 2009 4:32:32 PM]
gharen2
gharen2
I prefer to store client info in a dictionary with a username or the IPEndPoint as the key. Then you don't need to worry about indices.
Horup
Horup
Go with the solution gharen2 proposed.
Even if you did iterate through your indices and could decrement them, it looks like this could result in a race condition, since your working asynchronously.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.