简体   繁体   English

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

[英]Socket Programming: Server/Clients and Thread Usage

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;



    }

I want to write a chat program which has one server and 2 clients. 我想编写一个具有一台服务器和两个客户端的聊天程序。 The problem is that, I can not direct the message sent from the client1 to client2 via the server. 问题是,我无法通过服务器将从client1发送的消息定向到client2。 How can the server distinguish threads so that it can send the received message from client1 to client2? 服务器如何区分线程,以便可以将接收到的消息从client1发送到client2?

Each client has their own handle. 每个客户都有自己的句柄。 You can access this via the Handle property. 您可以通过Handle属性访问它。 For example: 例如:

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

Then all you need to do is store this in a hashtable, and iterate through it, looking for available data. 然后,您所需要做的就是将其存储在哈希表中,并对其进行迭代,以查找可用数据。 When you detect data on the wire for one of the connections, then save it and retransmit it to the other clients in the table. 当您检测到其中一个连接的电线上的数据时,请保存该数据并将其重新传输给表中的其他客户端。

Remember to make sure that you make this multithreaded so a listen request on one client does not block any send or receive functions on other clients! 请记住要确保使该线程成为多线程,这样一个客户端上的侦听请求不会阻止其他客户端上的任何发送或接收功能!

I've added some code here you should be able to work with (tested it out on my system) 我在这里添加了一些代码,您应该可以使用(在我的系统上测试过)

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;
        }

You will want to call HandleClients from a main thread that checks to see if there are any pending requests or not, and runs on a loop. 您将需要从主线程调用HandleClients ,该线程检查是否有任何待处理的请求,并在循环上运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM