【发布时间】:2017-04-15 20:55:12
【问题描述】:
我正在学习 c# 套接字编程。所以,我决定做一个 TCP 聊天,基本思路是 A 客户端向服务器发送数据,然后服务器将其广播给所有在线客户端(在这种情况下,所有客户端都在字典中)。
当有 1 个客户端连接时,它按预期工作,当连接超过 1 个客户端时出现问题。
服务器:
class Program
{
static void Main(string[] args)
{
Dictionary<int,TcpClient> list_clients = new Dictionary<int,TcpClient> ();
int count = 1;
TcpListener ServerSocket = new TcpListener(IPAddress.Any, 5000);
ServerSocket.Start();
while (true)
{
TcpClient client = ServerSocket.AcceptTcpClient();
list_clients.Add(count, client);
Console.WriteLine("Someone connected!!");
count++;
Box box = new Box(client, list_clients);
Thread t = new Thread(handle_clients);
t.Start(box);
}
}
public static void handle_clients(object o)
{
Box box = (Box)o;
Dictionary<int, TcpClient> list_connections = box.list;
while (true)
{
NetworkStream stream = box.c.GetStream();
byte[] buffer = new byte[1024];
int byte_count = stream.Read(buffer, 0, buffer.Length);
byte[] formated = new Byte[byte_count];
//handle the null characteres in the byte array
Array.Copy(buffer, formated, byte_count);
string data = Encoding.ASCII.GetString(formated);
broadcast(list_connections, data);
Console.WriteLine(data);
}
}
public static void broadcast(Dictionary<int,TcpClient> conexoes, string data)
{
foreach(TcpClient c in conexoes.Values)
{
NetworkStream stream = c.GetStream();
byte[] buffer = Encoding.ASCII.GetBytes(data);
stream.Write(buffer,0, buffer.Length);
}
}
}
class Box
{
public TcpClient c;
public Dictionary<int, TcpClient> list;
public Box(TcpClient c, Dictionary<int, TcpClient> list)
{
this.c = c;
this.list = list;
}
}
我创建了这个框,所以我可以为 Thread.start() 传递 2 个参数。
客户:
class Program
{
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
int port = 5000;
TcpClient client = new TcpClient();
client.Connect(ip, port);
Console.WriteLine("client connected!!");
NetworkStream ns = client.GetStream();
string s;
while (true)
{
s = Console.ReadLine();
byte[] buffer = Encoding.ASCII.GetBytes(s);
ns.Write(buffer, 0, buffer.Length);
byte[] receivedBytes = new byte[1024];
int byte_count = ns.Read(receivedBytes, 0, receivedBytes.Length);
byte[] formated = new byte[byte_count];
//handle the null characteres in the byte array
Array.Copy(receivedBytes, formated, byte_count);
string data = Encoding.ASCII.GetString(formated);
Console.WriteLine(data);
}
ns.Close();
client.Close();
Console.WriteLine("disconnect from server!!");
Console.ReadKey();
}
}
【问题讨论】:
-
您能描述一下连接多个客户端时会出现什么问题吗?现在我们只知道它“没有按预期工作”。
-
预期如果我向服务器发送“123”,那么服务器会将这个“123”发送给所有客户端。当只有 1 个客户端时它可以工作,但是当有超过 1 个客户端时,它就会出现问题,老实说,我不知道,也许我没有以正确的方式处理线程。
-
不清楚你在问什么。你的问题陈述太模糊了。您的代码有许多可以改进的地方。我看到的最严重的缺陷是在客户端代码中,您只执行一次读取操作,因为继续从用户那里获得更多输入。但是 TCP 不保证您会从任何已完成的读取操作中获得超过一个字节。因此,如果您的问题是客户端正在接收部分消息,这就是原因。请改进问题。请参阅 How to Ask 以及该页面底部的相关链接以获取建议。
-
如果你真的想学习网络编程,你应该从仔细而透彻地阅读Winsock Programmer's FAQ开始。它不是特定于 .NET,但 .NET API(实际上是大多数主流的低级网络 API)是基于套接字构建的,无论如何,该指南中的大多数建议都与协议有关,而不是与协议有关。 API。您还应该阅读许多其他有用的资源,但您应该从那里开始。
-
“它只是变得有问题”——也不是一个精确的问题陈述。代码中的另一个问题是字典类型不是线程安全的,因此如果侦听线程修改字典而另一个线程试图读取字典以发送消息,则读取线程将看到无效的损坏状态字典。
标签: c# sockets tcp chat tcplistener