C# - 多线程服务器 - 客户端流 [英] C# - multithreaded server - client streaming
问题描述
我已经实现了发送消息客户端 - >服务器并实际连接多个客户端。但我想要做的是连接2个客户端并让他们自己聊天。如果第三个客户连接 - 那么他就开始和其他客户聊天。
到现在为止,我正处于聊天客户端> server->客户端的舞台上与另一个c-> s-> c分开。会发生什么 - 我运行client1,一切正常。然后我运行client2并且使用它一切正常,但第一个客户端停止工作,然后我在第二个客户端上获得的第一条消息是我从client1发送的最后一条消息(但实际上并没有收到它服务器)。
所以我认为流有问题 - 两个客户以某种方式获得彼此的流。
这是一些部分服务器(相关的):
class TheServer
{
private TcpListener tcpListener;
private Thread threadListener;
TheMessage消息;
public TcpClient [] clientList = new TcpClient [ 100 跨度>];
private int n = 0 ;
public void StartServer()
{
尝试
{
此 .tcpListener = new TcpListener(IPAddress.Any, 8000 );
此 .threadListener = 新主题( new ThreadStart(ListenForClients));
this .threadListener.Start();
Console.WriteLine( 本地终点: + tcpListener.LocalEndpoint );
}
catch (例外e)
{
throw 跨度>;
}
}
私有 void ListenForClients( )
{
this .tcpListener.Start();
while ( true )
{
< span class =code-comment> // 阻止,直到客户端连接到服务器
TcpClient client = 此跨度> .tcpListener.AcceptTcpClient();
if (n == 0 )
{
clientList [ 0 ] =客户;
}
else
{
n ++;
clientList [n] =客户端;
}
// 创建线程来处理与连接客户端的通信
线程clientThread = new 线程( new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(clientList [n]);
}
}
private void HandleClientComm( object client)
{
TcpClient tcpClient =(TcpClient)client;
NetworkStream stm = clientList [n] .GetStream();
msg = new TheMessage();
while ( true )
{
< span class =code-sdkkeyword>字节 [] bSize = new 字节 [< span class =code-keyword> sizeof ( Int32 )];
stm.Read(bSize, 0 ,bSize.Length);
字节 [] bData = new 字节 [BitConverter.ToInt32(bSize, 0 )];
stm.Read(bData, 0 ,bData.Length);
msg = XmlRefactorServer.ByteArrayToObject< TheMessage>(bData);
String str = msg.Message;
Console.WriteLine(str);
stm.Flush();
// 发送回客户
msg.Message =海峡;
Byte [] bDataBack = XmlRefactorServer.ObjectToByteArray< TheMessage>(msg);
stm = clientList [n] .GetStream();
字节 [] bSizeBack = BitConverter.GetBytes(bDataBack.Length);
stm.Write(bSizeBack, 0 ,bSizeBack.Length);
stm.Write(bDataBack, 0 ,bDataBack.Length);
stm.Flush();
}
tcpClient.Close();
}
HandleClientComm(对象客户端)正在处理接收发送操作。
这里是客户端代码部分,它处理接收 - 发送操作:
while ( true )
{
msg.Message = Console.ReadLine( );
Byte [] bData = XmlRefacrotClient.ObjectToByteArray< TheMessage>(msg);
Stream stm = client.GetStream();
字节 [] bSize = BitConverter.GetBytes(bData.Length);
stm.Write(bSize, 0 ,bSize.Length);
stm.Write(bData, 0 ,bData.Length);
stm.Flush();
Console.WriteLine( 发送到服务器!);
// 从服务器读回来
Console.WriteLine( 从服务器收到!);
字节 [] bSizeBack = new 字节 [ sizeof ( Int32 )];
stm.Read(bSizeBack, 0 ,bSizeBack.Length);
字节 [] bDataBack = new 字节 [BitConverter.ToInt32(bSizeBack, 0 )];
stm.Read(bDataBack, 0 ,bDataBack.Length);
msg = XmlRefacrotClient.ByteArrayToObject< TheMessage>(bDataBack);
String str = msg.Message;
Console.WriteLine(str);
stm.Flush();
}
我得到
类型' System.OutOfMemoryException' $服务器上的p $ p> 字节 [] bData = new 字节 [BitConverter.ToInt32(bSize, 0 )];
sooo ..是的,溪流有问题(我认为)。
我对任何建议持开放态度。
解决方案
问题出在HandleClientComm()的开头并且确切地说:
private void HandleClientComm(对象客户端)
{
TcpClient tcpClient =(TcpClient)客户端;
NetworkStream stm = clientList [n] .GetStream();
msg = new TheMessage();
所以我必须得到''tcpClient''的流,而不是''clientList [n]''的流。
I have achieved sending message client -> server and actually connecting many clients simultaneously. But what I want to do is i.e. connect 2 clients and make them chat between themselves. And if 3rd client connects - then so he starts chatting with both other clients.
By now I am on the stage of chatting client->server->client separately from another c->s->c. What happens is - I run client1 and everything is OK. Then I run client2 and with it everything is OK, but the 1st client stops working and then the first message I acquire on the 2nd client is the last message that I sent from client1 (but that didn''t actually receive back to it from server).
So I suppose there''s problem with the streams - that the 2 clients somehow acquire each-other''s streams.
Here is the some parts of the server (relevant ones):
class TheServer
{
private TcpListener tcpListener;
private Thread threadListener;
TheMessage msg;
public TcpClient[] clientList = new TcpClient[100];
private int n = 0;
public void StartServer()
{
try
{
this.tcpListener = new TcpListener(IPAddress.Any, 8000);
this.threadListener = new Thread(new ThreadStart(ListenForClients));
this.threadListener.Start();
Console.WriteLine("Local end point: " + tcpListener.LocalEndpoint);
}
catch (Exception e)
{
throw;
}
}
private void ListenForClients()
{
this.tcpListener.Start();
while(true)
{
// block until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
if (n == 0)
{
clientList[0] = client;
}
else
{
n++;
clientList[n] = client;
}
// create thread to handle communication with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(clientList[n]);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream stm = clientList[n].GetStream();
msg = new TheMessage();
while (true)
{
Byte[] bSize = new Byte[sizeof(Int32)];
stm.Read(bSize, 0, bSize.Length);
Byte[] bData = new Byte[BitConverter.ToInt32(bSize, 0)];
stm.Read(bData, 0, bData.Length);
msg = XmlRefactorServer.ByteArrayToObject<TheMessage>(bData);
String str = msg.Message;
Console.WriteLine(str);
stm.Flush();
// send back to client
msg.Message = str;
Byte[] bDataBack = XmlRefactorServer.ObjectToByteArray<TheMessage>(msg);
stm = clientList[n].GetStream();
Byte[] bSizeBack = BitConverter.GetBytes(bDataBack.Length);
stm.Write(bSizeBack, 0, bSizeBack.Length);
stm.Write(bDataBack, 0, bDataBack.Length);
stm.Flush();
}
tcpClient.Close();
}
HandleClientComm(object client) is handling the receive-send operations.
And here is the client side code part, that handles the receive-send operations:
while (true)
{
msg.Message = Console.ReadLine();
Byte[] bData = XmlRefacrotClient.ObjectToByteArray<TheMessage>(msg);
Stream stm = client.GetStream();
Byte[] bSize = BitConverter.GetBytes(bData.Length);
stm.Write(bSize, 0, bSize.Length);
stm.Write(bData, 0, bData.Length);
stm.Flush();
Console.WriteLine("Sent to server!");
// reading back from server
Console.WriteLine("Received from server!");
Byte[] bSizeBack = new Byte[sizeof(Int32)];
stm.Read(bSizeBack, 0, bSizeBack.Length);
Byte[] bDataBack = new Byte[BitConverter.ToInt32(bSizeBack, 0)];
stm.Read(bDataBack, 0, bDataBack.Length);
msg = XmlRefacrotClient.ByteArrayToObject<TheMessage>(bDataBack);
String str = msg.Message;
Console.WriteLine(str);
stm.Flush();
}
And I get
An unhandled exception of type 'System.OutOfMemoryException' occurred in
in the Server at
Byte[] bData = new Byte[BitConverter.ToInt32(bSize, 0)];
sooo... yeah, there''s something wrong with the streams (on my opinion).
I am open for any suggestions.
解决方案 The problem was in the beginning of HandleClientComm() and precisely:
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream stm = clientList[n].GetStream();
msg = new TheMessage();
So I had to get the stream for ''tcpClient'', not not for ''clientList[n]''.
这篇关于C# - 多线程服务器 - 客户端流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!