C# - 多线程服务器 - 客户端流 [英] C# - multithreaded server - client streaming

查看:102
本文介绍了C# - 多线程服务器 - 客户端流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经实现了发送消息客户端 - >服务器并实际连接多个客户端。但我想要做的是连接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'    

 字节 [] 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆