gpt4 book ai didi

c# - 多线程 TCP 服务器回显给所有客户端

转载 作者:可可西里 更新时间:2023-11-01 02:51:07 25 4
gpt4 key购买 nike

我一直致力于通过服务器/客户端聊天室设置进行 TCP NAT 穿通。我已经在 UDP 中成功设置它,现在我想为 TCP 做同样的事情,因为我的套接字 atm 有点粗糙。

客户端可以通过任何方式正常连接并聊天和接收回声,但根据连接的数量,它将根据连接的客户端数量回显给发送消息的同一客户端。例如,3 个客户端已连接,客户端 2 发送一个 ping,它回显给客户端 2、3 次。它应该通过所有已连接用户的 IPEndPoint 列表循环并执行 sock.SendTo(data,data.Length,clients[i]);

但它会回显给发送消息的客户端。不知道我做错了什么,但我认为我做对了。但这让我很困扰。对我做错了什么的一些指导将不胜感激。

private static void Main(string[] args)
{
//create a socket
//create a end point to listen on
//bind
//listen
//accept the socket on a new socket
//receive
//store the connection in a list
//ping back on their socket
//go back to listening state

Console.Title = " TCP NAT PT Server";

StartServer();
}

private static void StartServer()
{
Thread ListenThread = new Thread(new ThreadStart(Listen));
ListenThread.Start();
Console.WriteLine("ListenThread: " + ListenThread.ThreadState);
}

private static void Listen()
{
try
{
server.Bind(ep);
server.Listen(0);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
while (true)
{
try
{
Socket handler = server.Accept();

Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientCommunication));
clientThread.Start((object)handler);
Console.WriteLine("ReceiveThread: " + clientThread.ThreadState);

string rstr = handler.RemoteEndPoint.ToString();
string[] rdata = rstr.Split(':');

IPEndPoint rep = new IPEndPoint(IPAddress.Parse(rdata[0]), int.Parse(rdata[1]));
clients.Add(rep);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}

private static void HandleClientCommunication(object Client)
{
Socket sock = (Socket)Client;
byte[] data = new byte[1024];
string str = string.Empty;

while (true)
{
try
{
int rec = sock.Receive(data, SocketFlags.None);
Array.Resize(ref data, rec);
str = Encoding.ASCII.GetString(data);
Console.WriteLine(sock.RemoteEndPoint.ToString() + " >> " + str);

//Console.WriteLine(clients.Count);
//Console.WriteLine(clients[0].Address + ":" + clients[0].Port);

string temp = Encoding.ASCII.GetString(data);
temp = "Echo: " + temp;
data = Encoding.ASCII.GetBytes(temp);
Console.WriteLine("Data.Length: " + temp.Length);

for (int i = 0; i < clients.Count; i++)
{
sock.SendTo(data, data.Length, SocketFlags.None, clients[i]);
//sock.Send(data, data.Length, SocketFlags.None);
}

data = new byte[1024];
}
catch (Exception e)
{
//socket error
Console.WriteLine(e.Message);
}
}

最佳答案

问题出在这一行:

 sock.SendTo(data, data.Length, SocketFlags.None, clients[i]);

根据 SendTo method doc :

If you are using a connection-oriented protocol, you must first establish a remote host connection by calling the Connect method or accept an incoming connection request using the Accept method

您正在使用连接到端点 A 的套接字通过 TCP 将字节发送到端点 B,这实际上是行不通的。

因此,与其在客户端中保留端点,不如在 listen 方法中保留套接字列表:

while (true)
{
try
{
Socket handler = server.Accept();

Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientCommunication));
clientThread.Start((object)handler);
Console.WriteLine("ReceiveThread: " + clientThread.ThreadState);

clients.Add(handler);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}

并更改用于向此发送消息的循环:

for (int i = 0; i < clients.Count; i++)
{
clients[i].Send(data);
}

请注意:为避免错误,您需要在客户端套接字关闭后从 clients 列表中删除项目。

关于c# - 多线程 TCP 服务器回显给所有客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38029993/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com