I'm new to C# and trying to write a Server-Client messaging application, I've done it with some cheating from internet but now I have a problem which I'm thinking over for a couple of days. My problem is, when I disconnect my client, and then reconnect it without stopping server, it (or they - because it's a multi-client app) can receive messages from the server but can not send messages (at least it does seem so in the messagebox of the server). I couldn't find out what the problem is.
Here is the codes: (not exactly all of the lines but the crucial parts)
Server:
public void OnSend(IAsyncResult ar)
{
try
{
clientSocket.EndSend(ar);
strName = "Server";
}
catch {}
}
private void OnAccept(IAsyncResult ar)
{
try
{
Socket clientSocket = serverSocket.EndAccept(ar);
serverSocket.BeginAccept(new AsyncCallback(OnAccept), null);
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket);
}
catch {}
}
private void OnReceive(IAsyncResult ar)
{
try
{
clientSocket = (Socket)ar.AsyncState;
clientSocket.EndReceive(ar);
Data msgReceived = new Data(byteData);
Data msgToSend = new Data();
byte[] message;
msgToSend.cmdCommand = msgReceived.cmdCommand;
msgToSend.strName = msgReceived.strName;
while (true)
{
switch (msgReceived.cmdCommand)
{
case Command.Login:
ClientInfo clientInfo = new ClientInfo
{
socket = clientSocket,
strName = msgReceived.strName
};
clientList.Add(clientInfo);
flag = true;
msgToSend.strMessage = "<<<" + msgReceived.strName + " has joined the room>>>";
break;
case Command.Logout:
int nIndex = 0;
foreach (ClientInfo client in clientList)
{
if (client.socket == clientSocket)
{
clientList.RemoveAt(nIndex);
break;
}
++nIndex;
}
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
flag = true;
msgToSend.strMessage = "<<<" + msgReceived.strName + " has left the room>>>";
break;
case Command.Message:
if (msgReceived.strMessage == "**disconnect**")
{
msgReceived.cmdCommand = Command.Logout;
disconnect = true;
continue;
}
else
msgToSend.strMessage = msgReceived.strMessage;
flag = false;
break;
case Command.List:
msgToSend.cmdCommand = Command.List;
msgToSend.strName = null;
msgToSend.strMessage = null;
foreach (ClientInfo client in clientList)
{
msgToSend.strMessage += client.strName + "*";
}
flag = false;
message = msgToSend.ToByte();
clientSocket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSend), clientSocket);
break;
}
break;
}
if (msgToSend.cmdCommand != Command.List)
{
message = msgToSend.ToByte();
foreach (ClientInfo clientInfo in clientList)
{
if ((clientInfo.socket != clientSocket || msgToSend.cmdCommand != Command.Login) && !disconnect)
{
clientInfo.socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSend), clientInfo.socket);
}
}
if (flag)
msgBox.AppendText(string.Format("{0}\r\n", msgToSend.strMessage));
else
msgBox.AppendText(string.Format("{0}: {1}\r\n", msgToSend.strName, msgToSend.strMessage));
}
if (msgReceived.cmdCommand != Command.Logout && !disconnect)
{
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket);
}
}
catch {}
}
Client:
private void OnSend(IAsyncResult ar)
{
try
{
clientSocket.EndSend(ar);
strName = usernameBox.Text.Trim();
}
catch {}
}
private void OnConnect(IAsyncResult ar)
{
try
{
clientSocket.EndConnect(ar);
Data msgToSend = new Data
{
cmdCommand = Command.Login,
strName = usernameBox.Text.Trim(),
strMessage = null
};
byte[] b = msgToSend.ToByte();
clientSocket.BeginSend(b, 0, b.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
if (clientSocket.Connected)
{
Data msgToSendConn = new Data
{
cmdCommand = Command.List,
strName = strName,
strMessage = null
};
byteData = msgToSendConn.ToByte();
clientSocket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
byteData = new byte[1024];
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), null);
Active(true);
}
}
catch {}
}
private void OnReceive(IAsyncResult ar)
{
try
{
clientSocket.EndReceive(ar);
Data msgReceived = new Data(byteData);
switch (msgReceived.cmdCommand)
{
case Command.Login:
clientListBox.Items.Add(msgReceived.strName);
break;
case Command.Logout:
clientListBox.Items.Remove(msgReceived.strName);
break;
case Command.Message:
break;
case Command.List:
clientListBox.Items.AddRange(msgReceived.strMessage.Split('*'));
clientListBox.Items.RemoveAt(clientListBox.Items.Count - 1);
msgBox.Text += "<<<" + strName + " has joined the room>>>\r\n";
break;
}
if (msgReceived.strMessage.Length > 0 && msgReceived.cmdCommand != Command.List)
msgBox.AppendText(string.Format("{0}: {1}\r\n", msgReceived.strName, msgReceived.strMessage));
byteData = new byte[1024];
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), null);
}
catch {}
}
private void connBtn_Click(object sender, EventArgs e)
{
...validating ip and port number in textboxes...
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iPEndPoint = new IPEndPoint(ip, port);
try
{
clientSocket.BeginConnect(iPEndPoint, new AsyncCallback(OnConnect), null);
}
catch {}
private void disconnBtn_Click(object sender, EventArgs e)
{
Data msgToSend = new Data
{
strName = strName,
strMessage = "**disconnect**",
cmdCommand = Command.Message
};
byte[] byteData = msgToSend.ToByte();
clientSocket.Send(byteData, 0, byteData.Length, SocketFlags.None);
clientSocket.Close();
}
private void sendMsgBtn_Click(object sender, EventArgs e)
{
if (sendMsgBox.Text.Length > 0)
{
try
{
Data msgToSend = new Data
{
strName = strName,
strMessage = sendMsgBox.Text.Trim(),
cmdCommand = Command.Message
};
byte[] byteData = msgToSend.ToByte();
clientSocket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
sendMsgBox.Clear();
}
catch {}
}
}
The Data class and Command enum which are same in both Server and Client:
enum Command
{
Login,
Logout,
Message,
List,
Null
}
class Data
{
public string strName;
public string strMessage;
public Command cmdCommand;
public Data()
{
cmdCommand = Command.Null;
strMessage = null;
strName = null;
}
public Data(byte[] data)
{
cmdCommand = (Command)BitConverter.ToInt32(data, 0);
int nameLen = BitConverter.ToInt32(data, 4);
int msgLen = BitConverter.ToInt32(data, 8);
if (nameLen > 0)
strName = Encoding.UTF8.GetString(data, 12, nameLen);
else
strName = null;
if (msgLen > 0)
strMessage = Encoding.UTF8.GetString(data, 12 + nameLen, msgLen);
else
strMessage = "";
}
public byte[] ToByte()
{
List<byte> result = new List<byte>();
result.AddRange(BitConverter.GetBytes((int)cmdCommand));
if (strName != null)
result.AddRange(BitConverter.GetBytes(strName.Length));
else
result.AddRange(BitConverter.GetBytes(0));
if (strMessage != null)
result.AddRange(BitConverter.GetBytes(strMessage.Length));
else
result.AddRange(BitConverter.GetBytes(0));
if (strName != null)
result.AddRange(Encoding.UTF8.GetBytes(strName));
if (strMessage != null)
result.AddRange(Encoding.UTF8.GetBytes(strMessage));
return result.ToArray();
}
}