【问题标题】:C# How would I go about connecting multiple clients to the same server?C# 如何将多个客户端连接到同一台服务器?
【发布时间】:2016-05-03 18:41:51
【问题描述】:

我在客户端服务器端工作,对 .net 和 C# 不太熟悉,想知道如何将多个客户端连接到同一台服务器。如果可以的话,我宁愿继续使用 TcpClient。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Net;
    using System.Net.Sockets;
    using System.IO;
    using Microsoft.VisualBasic;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.Threading;

  namespace TFServerClient
   {
      public partial class Form1 : Form
    {
      private TcpClient client;
      public StreamReader STR;
      public StreamWriter STW;
      public string receive;
      public String text_to_send;
      TcpListener listener;

    public Form1()
    {
        InitializeComponent();

        IPAddress[] localIP = Dns.GetHostAddresses(Dns.GetHostName()); //gets my IP
        foreach(IPAddress address in localIP)
        {
            if(address.AddressFamily == AddressFamily.InterNetwork)
            {
                txtIPServer.Text = address.ToString();
            }
        }
    }

    private void btnStartServer_Click(object sender, EventArgs e)
    {
        ListenBackground.RunWorkerAsync();
    }

    private void ReceiveData_DoWork(object sender, DoWorkEventArgs e)
    {
        while(client.Connected)
        {
            try
            {
                receive = STR.ReadLine();
                this.txtChat.Invoke(new MethodInvoker(delegate () { txtChat.AppendText("You: " + receive + "\n"); }));
                receive = "";
            }
            catch (Exception x)
            {
                MessageBox.Show(x.Message.ToString());
            }
        }
    }

    private void SendData_DoWork(object sender, DoWorkEventArgs e)
    {
        if(client.Connected)
        {
            STW.WriteLine(text_to_send);
            this.txtChat.Invoke(new MethodInvoker(delegate () { txtChat.AppendText("Me: " + text_to_send + "\n"); }));
        }
        else
        {
            MessageBox.Show("Send failed");
        }
        SendData.CancelAsync();
    }

    private async void ListenBackground_DoWork(object sender, DoWorkEventArgs e)
    {
        this.txtChat.Invoke(new MethodInvoker(delegate () { txtChat.AppendText("Awaiting Connection...\n"); }));
        client = listener.AcceptTcpClient();
        this.txtChat.Invoke(new MethodInvoker(delegate () { txtChat.AppendText("Client Connected.\n"); }));
        STR = new StreamReader(client.GetStream());
        STW = new StreamWriter(client.GetStream());
        STW.AutoFlush = true;

        ReceiveData.RunWorkerAsync(); //Start recieving data in background
        SendData.WorkerSupportsCancellation = true; //able to cancel thread
    }

    private void btnConnect_Click(object sender, EventArgs e)
    {
        client = new TcpClient();
        IPEndPoint IP_End = new IPEndPoint(IPAddress.Parse(txtIPClient.Text), int.Parse(txtPortClient.Text));

        try {
            client.Connect(IP_End);
            if(client.Connected)
            {
                txtChat.AppendText("Connected To Server " + "\n");
                STW = new StreamWriter(client.GetStream());
                STR = new StreamReader(client.GetStream());
                STW.AutoFlush = true;

                ReceiveData.RunWorkerAsync(); //Start recieving data in background
                SendData.WorkerSupportsCancellation = true; //able to cancel thread
            }
        } catch(Exception x)
        {
            MessageBox.Show(x.Message.ToString());
        }
    }

    private void btnSend_Click(object sender, EventArgs e)
    {
        if(txtMessage.Text != "")
        {
            text_to_send = txtMessage.Text;
            SendData.RunWorkerAsync();
        }
        txtMessage.Text = "";
    }
}
}

【问题讨论】:

  • 您已发布代码并解释了您正在处理的内容,但是您没有说明当前代码、问题是什么......请编辑问题并说明您遇到的现有问题使用当前代码。 This is not a Code Factory Service网站..!
  • 如果你打开你的应用两次并连接它们,那么你有多个连接的客户端......你是这个意思吗?
  • 当前代码只允许一个客户端连接然后停止。我需要弄清楚如何让多个客户端连接到聊天服务器。我不知道该怎么做。打开多个不起作用,因为我的代码只监听一个。
  • 考虑对网络 API 进行编程 - 在您使用的任何 UI 之外。代码不必要地与对服务器毫无意义的回调方法进行了合并——服务器应该使用 System.NET 或更高级别的 API(例如,Web api 自托管)。

标签: c# .net server client


【解决方案1】:

听起来您只需要对服务器端代码进行多线程处理,类似于以下内容:

listener = new TcpListener(ipAddress, portNumber);
listener.Start();

while (true)
{
    var client = listener.AcceptTcpClient();
    var thread = new Thread(new ThreadStart(() => SOME ACTION));
}

传递给 ThreadStart 构造函数的委托将处理创建流读取器和流写入器。它还应该执行您想要执行的任何服务器端业务逻辑。

AcceptTcpClient 方法是一种阻塞方法,因此只有在每次收到来自客户端的 TCP 请求时才会创建一个新的 Thread 实例。

可以找到此类操作的示例:

Here@csharp.net-informations.com

Here@codeproject.com

警告:在 codeproject.com 查看与文章相关的下载内容即表示您同意服务条款和文章的许可。许可证是代码项目开放许可证 (CPOL)

【讨论】:

    【解决方案2】:

    有一个非常棒的免费库,名为 NetSockets,您可以使用它。 (https://netsockets.codeplex.com/)

    该库是 TCP 和多线程的,这里是如何使用它:

    • 服务器端:

    创建服务器:

    static NetObjectServer server = new NetObjectServer();
    

    启动服务器:

    server.Start(IPAddress.Any, 7482);
    

    事件处理程序:

    server.OnClientAccepted += server_OnClientAccepted;
    
    server.OnClientConnected += server_OnClientConnected;
    
    server.OnClientDisconnected += server_OnClientDisconnected;
    
    server.OnClientRejected += server_OnClientRejected;
    
    server.OnReceived += server_OnReceived;
    
    server.OnStarted += server_OnStarted;
    
    server.OnStopped += server_OnStopped;
    
    • 客户端:

    创建客户端:

    static readonly NetObjectClient client = new NetObjectClient();
    

    事件处理程序:

    client.OnConnected += client_OnConnected;
    
    client.OnDisconnected += client_OnDisconnected;
    
    client.OnReceived += client_OnReceived;
    

    连接:

    client.TryConnect("127.0.0.1",7482);
    

    此信息取自 Joseph Bisaillon 的博客 (http://www.josephbisaillon.com/)

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
    • 感谢您的评论,我已修复它! :)
    • 其实没有。您仍然提供了一个不必要的第三方库来完成可以使用标准 .net 资源完成的工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    • 2015-06-13
    • 1970-01-01
    相关资源
    最近更新 更多