【问题标题】:C# Socket Programming With Multiclients使用多客户端进行 C# 套接字编程
【发布时间】:2017-05-16 09:24:43
【问题描述】:

我正在制作一个客户端-服务器程序。有两种客户端形式和一种服务器形式。程序非常适合 1v1 连接,但另一台机器与服务器连接时无法连接。我想与多客户端一起制作。

这里是代码。

服务器.cs

private TcpListener ConnectionListener;//variable needed to listen for connections
    private BinaryReader MessageReader;//variable for reading messages
    private BinaryWriter MessageWriter;//variable for writing messages
    private Socket ClientConnection = new Socket(System.Net.Sockets.AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//variable for holding the client connection
    private NetworkStream DataStream;//variable for keeping server and client in a stream and synchronized
    private Thread ListeningThread;//variable that is assigned to a thread listening for incoming connections and preventing the pc from blocking

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        System.Environment.Exit(System.Environment.ExitCode);//exit and close all threads and release all recources
    }

    //functions used for networks
    private void ListenForConnections()
    {
        //try listening with the given ip address
        try
        {
            ConnectionListener = new TcpListener(IPAddress.Parse(txt_Ip.Text), 80);//listen to given ip on port 80 allways
            ConnectionListener.Start();//start listening;
            ChangeTextBoxContent("Bağlantılar Dinleniyor.");
            ClientConnection = ConnectionListener.AcceptSocket();//wait untill client connects (blocking function) if connected return a socket 
            DataStream = new NetworkStream(ClientConnection);//initialize a stream 
            MessageReader = new BinaryReader(DataStream);//use reader within the stream
            MessageWriter = new BinaryWriter(DataStream);//use writer within the stream
            ChangeTextBoxContent("Bağlantı Alındı.");
            Thread acceptThread = new Thread(new ThreadStart(HandleConnection));
            acceptThread.Start();
            MessageReader.Close();//close the reader;
            MessageWriter.Close();//close the writer;
            DataStream.Close();//close the stream;
            ClientConnection.Close();//close thre connection
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());//signal the error in a message box
        }
    }
    private void HandleConnection()
    {
        string message;
        //loop until infinity
        do
        {
            //try reading from the data stream if anything went wrong with the connection break
            try
            {
                message = MessageReader.ReadString();//read message
                ChangeTextBoxContent(message);//call the function that manipulates text box from a thread and change the contents.
            }
            catch (Exception)
            {
                ChangeTextBoxContent("Bağlantı Kayboldu.");
                break;//get out of the while loop
            }
        } while (true);
    }
    private void ChangeTextBoxContent(string tx)
    {
        if (txt_mesajlar.InvokeRequired)//if the messages text box needs a delegate invoking
        {
            Invoke(new UpdateTextBox(ChangeTextBoxContent), new object[] { tx });
        }
        else
        {
            //if no invoking required then change
            txt_mesajlar.Text += tx + "\r\n";//concatinate the original with the given message and a new line
        }
    }

    private void btn_start_listen_Click(object sender, EventArgs e)
    {
        try
        {
            IPAddress.Parse(txt_Ip.Text);//
            ListeningThread = new Thread(new ThreadStart(ListenForConnections));//assign thread variable with the blocking function
            ListeningThread.Start();//start the thread that will wait for connections
        }
        catch (Exception)
        {
            MessageBox.Show("Yanlış Ip Adresi");//signal the error in a message box
        }
    }

和客户的代码

   private TcpClient Client;//variable needed to listen for connections
    private BinaryReader MessageReader;//variable for reading messages
    private BinaryWriter MessageWriter;//variable for writing messages
    private NetworkStream DataStream;//variable for keeping server and client in a stream and synchronized
    private Thread ClientThread;//variable that is assigned to a thread listening for incoming connections and preventing the pc from blocking

    public int MachineState = 0;   // active-passive state
    public int MachineStatus = 0;  // on-off state
    public string MachineName = "Cnc1";
    public int counterfortimerdebug = 0;
    public Form1()
    {
        InitializeComponent();

        MachineStatus = 1;  // Machine Opened

        try
        {
            MachineState = 1;
            IPAddress.Parse("127.0.0.1");
            ClientThread = new Thread(new ThreadStart(PerformConnection));
            ClientThread.Start();
        }
        catch (Exception Ex)
        {
            MessageBox.Show(Ex.ToString());
        }

    }


    private void Form1_Load(object sender, EventArgs e)
    {
        lb_gcodes.Items.Add("01000");
        lb_gcodes.Items.Add("T1 M6");
        lb_gcodes.Items.Add("G0 G90 G40 G21 G17 G94 G80");
        lb_gcodes.Items.Add("G54 X-75 Y-25 S500 M3");
        lb_gcodes.Items.Add("G43 Z100 H1");
        lb_gcodes.Items.Add("Z5");
        lb_gcodes.Items.Add("G1 Z-20 F100");
        lb_gcodes.Items.Add("X-50 M8");
        lb_gcodes.Items.Add("X0 Y50");
        lb_gcodes.Items.Add("X50 Y0");
        lb_gcodes.Items.Add("G0 Z100");
        lb_gcodes.Items.Add("M30");

    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        System.Environment.Exit(System.Environment.ExitCode);//exit and close all threads and release all recources
    }

    //network functions used
    private void PerformConnection()
    {

        try
        {
            Client = new TcpClient();
            ChangeTextBoxContent("Bağlanıyor......");
            Client.Connect(IPAddress.Parse("127.0.0.1"), 80);
            DataStream = Client.GetStream();
            MessageReader = new BinaryReader(DataStream);
            MessageWriter = new BinaryWriter(DataStream);
            MessageWriter.Write(MachineName + " " + "Bağlandı..");
            ChangeTextBoxContent("Bağlandı..");
            HandleConnection();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }
    private void HandleConnection()
    {
        string message;
        //loop until infinity
        do
        {
            //try reading from the data stream if anything went wrong with the connection break
            try
            {
                message = MessageReader.ReadString();//read message
                ChangeTextBoxContent(message);//call the function that manipulates text box from a thread and change the contents.
            }
            catch (Exception ex)
            {
                ChangeTextBoxContent(ex.ToString());
                break;
            }
        } while (true);
    }
    private void ChangeTextBoxContent(string tx)
    {
        if (txt_mesajlar.InvokeRequired)
        {
            Invoke(new UpdateTextBox(ChangeTextBoxContent), new object[] { tx });
        }
        else
        {
            //if no invoking required then change
            txt_mesajlar.Text += tx + "\r\n";//concatinate the original with the given message and a new line
        }
    }

感谢您的帮助。

【问题讨论】:

  • AcceptSocket 应该循环调用。

标签: c# multithreading sockets


【解决方案1】:

你可以看到我的类具有相同的功能:

 public delegate void Message(string message, IPAddress from);
    public class Listener : IDisposable
    {
        private readonly TcpListener _tcp;
        private Message _OnRecieve;
        private Thread _listenThread;
        private bool IsStopped = false;
        public Listener(IPAddress ip, int port, Message f)
        {
            _tcp = new TcpListener(ip, port);
            _OnRecieve = f;
        }
        public void Start()
        {
            _listenThread = new Thread(ListenForClients);
            _listenThread.Start();
        }
        public void Stop()
        {
            if (_tcp != null)
            {
                _listenThread.Abort();
                _tcp.Stop();
                IsStopped = true;
            }
        }
        private void ListenForClients()
        {
            _tcp.Start();
            while (!IsStopped)
            {
                TcpClient client = _tcp.AcceptTcpClient();
                var clientThread = new Thread(HandleClientComm);
                clientThread.Start(client);
            }
        }
        private void HandleClientComm(object client)
        {
            ReadMessage((TcpClient)client);
        }
        void IDisposable.Dispose()
        {
            if (_tcp != null)
            {
                _listenThread.Abort();
                _tcp.Stop();
                IsStopped = true;
            }
        }
        private void ReadMessage(TcpClient client)
        {
            try
            {
                NetworkStream ns = client.GetStream();
                string msg = ... /// read message
                _OnRecieve(msg,client.(client.Client.RemoteEndPoint as IPEndPoint).Address;
                client.Close();  
            }
            catch (Exception exc)
            {

                client.Close();
                throw exc;
            }
        }
    }

及用法:

        public void NetworkGet(string s, System.Net.IPAddress ip)
        {
           // do anything
        }
        public Server()
        {
            listener = new Network.Listener(System.Net.IPAddress.Any, Properties.Main.Default.NetworkPort, NetworkGet);
            listener.Start();  
        }

【讨论】:

    【解决方案2】:

    只需更新 Method 并添加 bool 变量即可停止监听:

    private void ListenForConnections()
    {
    while(!IsStopped)
        //try listening with the given ip address
        ....
    }
    }
    

    【讨论】:

    • 首先:你有全局流变量——这很糟糕,在你需要它们的地方声明 NetworkStream 和 BinaryReader\Writer。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    • 2021-02-09
    • 1970-01-01
    • 1970-01-01
    • 2014-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多