c# program runs improperly after disconnecting socket

Viewed 46

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();
    }
}
0 Answers
Related