0

I'm kind of new to this ask-answer thing, please let me know if I've done any mistakes. I have this server program, running on my laptop. Server is a console application;

class Program
{
    static void Main(string[] args)
    {
        Server sv = new Server("192.168.2.69", 52025);
        sv.OnClientAccept += new ClientAcceptHandler(sv_OnClientAccept);
        sv.OnClientMessage += new ClientMessageHandler(sv_OnClientMessage);
        sv.Start();
    }

    static void sv_OnClientMessage(Server s, System.Net.Sockets.TcpClient client, string message)
    {
        Console.WriteLine("Message received from client " + GetClientIp(client) + ": \"" + message + "\"");
        string msgToAll = message;
        s.SendToAllClients(msgToAll);
        Console.WriteLine("Message sent: \"" + message + "\" to the clients:");
        foreach (TcpClient cl in s.Clients)
        {
            Console.WriteLine(GetClientIp(cl));
        }
    }

    static void sv_OnClientAccept(Server s, System.Net.Sockets.TcpClient client)
    {
        Console.WriteLine("Client Accepted : " + GetClientIp(client));
    }

    static string GetClientIp(TcpClient Client)
    {
        return ((IPEndPoint)Client.Client.RemoteEndPoint).Address.ToString();
    }

}

The Server class;

public delegate void ClientAcceptHandler(Server s, TcpClient client);

public delegate void ClientMessageHandler(Server s, TcpClient client, string message);

public class Server
{

    private List<TcpClient> clients = new List<TcpClient>();

    object lockObjc;

    private TcpListener server;

    private string ip;

    private int port;

    private Thread accepter, listener;



    public List<TcpClient> Clients { get { return this.clients; } set { this.clients = value; } }

    public event ClientAcceptHandler OnClientAccept;

    public event ClientMessageHandler OnClientMessage;



    public Server(string IP, int Port)
    {
        ip = IP;
        port = Port;
    }

    private void ClientAccepted(TcpClient Client)
    {
        if (OnClientAccept != null)
        {
            OnClientAccept.Invoke(this, Client);
        }
    }

    private void ClientMessaged(TcpClient Client, string Message)
    {
        if (OnClientMessage != null)
        {
            OnClientMessage.Invoke(this, Client, Message);
        }
    }

    public void Start()
    {
        lockObjc = new object();
        IPAddress ipAddress = IPAddress.Parse(ip);//127.0.0.1 -> local || "192.168.2.69" -> laptop
        server = new TcpListener(ipAddress, port);//2014 -> local || 52025
        server.Start();

        accepter = new Thread(AcceptClients);
        accepter.Start();

        listener = new Thread(Listen);
        listener.Start();
    }

    private void AcceptClients()
    {
        while (true)
        {
            TcpClient attachedCl = server.AcceptTcpClient();
            if (attachedCl != null)
            {
                lock (lockObjc)
                {
                    if (!clients.Contains(attachedCl))
                    {
                        clients.Add(attachedCl);
                        ClientAccepted(attachedCl);
                    }
                }
            }
        }
    }

    private void Listen()
    {
        while (true)
        {
            for (int i = 0; i < clients.Count; i++)
            {
                TcpClient client = clients[i];
                lock (lockObjc)
                {
                    try
                    {
                        StreamReader clientIn = new StreamReader(client.GetStream());
                        string msg = clientIn.ReadLine();
                        if (msg != string.Empty)
                        {
                            ClientMessaged(client, msg);
                        }
                    }
                    catch
                    {
                    }
                }
            }
        }
    }

    private bool send(TcpClient Client, string Msg)
    {
        bool b = true;
        try
        {
            TcpClient client = Client;
            StreamWriter clientOut = new StreamWriter(client.GetStream());
            clientOut.AutoFlush = true;
            clientOut.WriteLine(Msg);
        }
        catch
        {
            b = false;
        }
        return b;
    }



    public bool SendToACLient(TcpClient Client, string Message)
    {
        return send(Client, Message);
    }

    public bool SendToAClient(int i, string Message)
    {
        return send(clients[i], Message);
    }

    public bool SendToAllClients(string Message)
    {
        bool b = true;
        for (int i = 0; i < clients.Count; i++)
        {
            b = b && send(clients[i], Message);
        }
        return b;
    }

    public bool SendToAllClientsExcept(TcpClient Client, string Message)
    {
        int x = clients.IndexOf(Client);
        bool b = true;
        for (int i = 0; i < clients.Count; i++)
        {
            if (i != x)
            {
                b = b && send(clients[i], Message);
            }
        }
        return b;
    }

}

Since I'm really new to server-client relationships, I don't know if the server part is OK, but it seems OK to me programmatically (But I'm also amateur programer, no real education).

And the client part is;

public delegate void ServerMessageHandler(Client Receiver, string Message);

public class Client
{

    private StreamReader clientIn;

    private StreamWriter clientOut;

    private TcpClient client;

    private Thread listener;

    private object lockObj;



    public event ServerMessageHandler OnServerMessage;

    public bool Connected { get { return (client != null && client.Connected); } }



    public Client()
    {
        lockObj = new object();

        client = new TcpClient();

        listener = new Thread(Listen);
    }



    private void ServerMessaged(string Message)
    {
        if (OnServerMessage != null)
        {
            OnServerMessage.Invoke(this, Message);
        }
    }

    private void Listen()
    {
        string serverMsg;
        while (true)
        {
            try
            {
                serverMsg = clientIn.ReadLine();
                if (serverMsg != string.Empty)
                {
                    ServerMessaged(serverMsg);
                }
            }
            catch
            {
            }
        }
    }

    private void start()
    {
        listener.Start();
    }



    public bool Connect(string Ip, int Port)
    {
        client.Connect(Ip, Port);//"192.168.2.69", 52025
        if (client.Connected)
        {
            clientIn = new StreamReader(client.GetStream());
            clientOut = new StreamWriter(client.GetStream());

            clientOut.AutoFlush = true;

            start();

        }
        return client.Connected;
    }

    public void Send(string Message)
    {
        if (client.Connected)
        {
            clientOut.WriteLine(Message);
        }
    }

}

Here's the form that I run Client class;

 public partial class Form1 : Form
{
    string s;
    Client c;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        c = new Client();
        c.OnServerMessage += new ServerMessageHandler(c_OnServerMessage);
        bool b = c.Connect("192.168.2.69", 52025);
        if (b)
        {
            s += "Connected to the server: 192.168.2.69:52025\r\n";
        }
        timer1.Start();
    }

    void c_OnServerMessage(Client Receiver, string Message)
    {
        s += "Server: " + Message + "\r\n";
    }

    private void button1_Click(object sender, EventArgs e)
    {
        c.Send(textBox1.Text);
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        textBox2.Text = s;
    }

    private void textBox1_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            c.Send(textBox1.Text);
        }
    }

}

This form has two textboxes, first one is the one which takes user input (textBox1), the second one is the one which shows server responds. Why I'm not using Console? Because I've tried it in a way which I was waiting an input from user (Console.ReadLine) which as far as I know locks the console until user presses enter, even tough I'm using a thread for listening the server, I wasn't able to show the server answer on console.

So, I decided to create my own console (sort-of). The reason I run a timer to show messages is I get an error when I try to change the textbox text from a method that is being called by a thread (which is the c_OnServerMessage method, being called, indirectly, from the Listener thread from Client class)

But the problem I get here is this: I run the server on my laptop, I also run one client on my laptop which goes perfectly fine until I open up another client on another computer. At that point things go this way: I send a message from a client, the message reaches the server and is sent back. When I send another message, that message does not reach the server until I send a message from Client 2. And when I send a message from Client 2, the server gets the message from Client 2 even tough I sent the message from Client 1 first.

So basically what happens is, if I run 2 clients, I cannot send 2 messages in a row from a client, it kind of acts like a chess game where there is a turn for playing. I really don't understand the reason.

This problem is probably from a basic mistake but I had to write this whole message to be able to express myself. Thank you for your patient and your helps.

EDIT: Problem solved thanks to this: TCP server with multiple Clients My problem was the Listen method from Server class. The Listen method is being called by a thread, but still it runs a for loop in itself. Which if loop stops and waits for something, thread wouldn't make any difference. Thanks again, i think i will keep question, because i do not know what should happen to solved problems.

Kristof U.
  • 1,263
  • 10
  • 17
welrocken
  • 266
  • 1
  • 9
  • 2
    Please write Question first. Not clear to me after 5 screens of text – lordkain Jul 01 '14 at 21:23
  • I suspect the problem is with the locking you've got. You've got a lot of threads locking on a single object, but it's not at all clear why. – Jon Skeet Aug 26 '14 at 05:46

0 Answers0