套接字编程:服务器/客户端和线程使用

时间:2012-12-21 20:22:08

标签: c# multithreading sockets tcpclient

static void Main(string[] args)
    {
        Console.Title = "Socket Server";
        Console.WriteLine("Listening for client messages");

        Socket serverSocket = new Socket(AddressFamily.InterNetwork,
                                         SocketType.Stream,
                                         ProtocolType.Tcp);
        IPAddress serverIp = IPAddress.Any;
        IPEndPoint serverEP = new IPEndPoint(serverIp, 8000);

        SocketPermission socketPermission = new SocketPermission(NetworkAccess.Accept,
                                                                 TransportType.Tcp,
                                                                 "127.0.0.1", 8000);

        serverSocket.Bind(serverEP);
        serverSocket.Listen(2);


        while(true)
        {
            //Socket connection = serverSocket.Accept();

            connection = serverSocket.Accept();

            Thread clientThread = new Thread(new ParameterizedThreadStart(MultiUser));           
            clientThread.Start(connection);


        }
    }

    public static void MultiUser(object connection)
    {

        byte[] serverBuffer = new byte[10025];
        string message = string.Empty;

        int bytes = ((Socket)connection).Receive(serverBuffer, serverBuffer.Length, 0);
        message += Encoding.ASCII.GetString(serverBuffer, 0, bytes);
        Console.WriteLine(message);

        TcpClient client = new TcpClient();
        client.Client = ((Socket)connection);
        IntPtr handle = client.Client.Handle;



    }

我想写一个有一个服务器和两个客户端的聊天程序。问题是,我无法通过服务器将客户端1发送的消息指向客户端2。服务器如何区分线程,以便它可以将收到的消息从client1发送到client2?

1 个答案:

答案 0 :(得分:1)

每个客户都有自己的句柄。您可以通过句柄属性访问它。例如:

TcpClient client = tcpListener.AcceptTcpClient();
IntPtr handle = client.Client.Handle; //returns a handle to the connection

然后您需要做的就是将其存储在哈希表中,并遍历它,查找可用数据。当您在其中一个连接上检测到线路上的数据时,请将其保存并重新传输到表中的其他客户端。

请记住确保您创建此多线程,以便一个客户端上的侦听请求不会阻止其他客户端上的任何发送或接收函数!

我在这里添加了一些你应该可以使用的代码(在我的系统上测试过)

private void HandleClients(object newClient)
        {
            //check to see if we are adding a new client, or just iterating through existing clients
            if (newClient != null)
            {
                TcpClient newTcpClient = (TcpClient)newClient;

                //add this client to our list
                clientList.Add(newTcpClient.Client.Handle, newTcpClient);
                Console.WriteLine("Adding handle: " + newTcpClient.Client.Handle);  //for debugging
            }

            //iterate through existing clients to see if there is any data on the wire
            foreach (TcpClient tc in clientList.Values)
            {
                if (tc.Available > 0)
                {
                    int dataSize = tc.Available;
                    Console.WriteLine("Received data from: " + tc.Client.Handle); //for debugging

                    string text = GetNetworkString(tc.GetStream());

                    //and transmit it to everyone else
                    foreach (TcpClient otherClient in clientList.Values)
                    {
                        if (tc.Client.Handle != otherClient.Client.Handle)
                        {
                            Send(otherClient.GetStream(), text);
                        }
                    }
                }
            }
        }

        public void Send(NetworkStream ns, string data)
        {
            try
            {
                byte[] bdata = GetBytes(data, Encoding.ASCII);
                ns.Write(bdata, 0, bdata.Length);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
        }

        protected string GetNetworkString(NetworkStream ns)
        {
            if (ns.CanRead)
            {
                string receivedString;
                byte[] b = GetNetworkData(ns);

                receivedString = System.Text.Encoding.UTF8.GetString(b);
                log.Info("Received string: " + receivedString);

                return receivedString;
            }
            else
                return null;
        }

        protected byte[] GetNetworkData(NetworkStream ns)
        {
            if (ns.CanRead)
            {
                log.Debug("Data detected on wire...");
                byte[] b;
                byte[] myReadBuffer = new byte[1024];
                MemoryStream ms = new MemoryStream();
                int numberOfBytesRead = 0;

                // Incoming message may be larger than the buffer size.
                do
                {
                    numberOfBytesRead = ns.Read(myReadBuffer, 0, myReadBuffer.Length);
                    ms.Write(myReadBuffer, 0, numberOfBytesRead);
                }
                while (ns.DataAvailable);

                //and get the full message
                b = new byte[(int)ms.Length];
                ms.Seek(0, SeekOrigin.Begin);
                ms.Read(b, 0, (int)ms.Length);
                ms.Close();

                return b;
            }
            else
                return null;
        }

您需要从主线程调用 HandleClients ,该主线程检查是否有任何待处理请求,并在循环上运行。