Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 接收消息并通过NetworkStream向客户端发送消息_C#_Tcplistener_Networkstream - Fatal编程技术网

C# 接收消息并通过NetworkStream向客户端发送消息

C# 接收消息并通过NetworkStream向客户端发送消息,c#,tcplistener,networkstream,C#,Tcplistener,Networkstream,我有一个关于在C#中通过网络流从TCPListener服务器向客户端发送和接收消息的问题。现在,我的TCPListener实例可以从客户端接收一条消息并将其写入服务器控制台,它可以接受一个输入字符串并将其发送回客户端。但我希望改进该功能,以接受来自客户端的多个连续消息,并将多个连续响应发送回客户端。如果NetworkStream的ReadAsync和WriteAsync函数可以处理接收多个连续消息或发送多个连续消息,以及是否有更好的方法来实现这一点,是否有人碰巧有任何指针?此外,由于Consol

我有一个关于在C#中通过网络流从TCPListener服务器向客户端发送和接收消息的问题。现在,我的TCPListener实例可以从客户端接收一条消息并将其写入服务器控制台,它可以接受一个输入字符串并将其发送回客户端。但我希望改进该功能,以接受来自客户端的多个连续消息,并将多个连续响应发送回客户端。如果NetworkStream的ReadAsync和WriteAsync函数可以处理接收多个连续消息或发送多个连续消息,以及是否有更好的方法来实现这一点,是否有人碰巧有任何指针?此外,由于Console.ReadLine函数将在服务器从未收到来自ReadLine的任何用户输入(且未按下Enter键)的情况下被阻止,因此是否有方法测试是否有来自键盘的可选用户输入?这样,只有当服务器接收到来自用户的某种控制台输入时,我才能尝试执行sendmessage命令,否则就可以继续接收客户端消息

   public static async Task getMessage(TcpListener server)
      {
            byte[] bytes = new byte[256];
            using (var theStream = await server.AcceptTcpClientAsync())
            {
                using (var tcpStream = theStream.GetStream())
                {

                    await tcpStream.ReadAsync(bytes, 0, bytes.Length);
                    var msg = Encoding.UTF8.GetString(bytes);
                    Console.WriteLine(msg);
                    var payload = Console.ReadLine();
                    var bytes2 = Encoding.UTF8.GetBytes(payload);
                    await tcpStream.WriteAsync(bytes2, 0, bytes2.Length);
                }

           }

      } 

有趣的是,看到一个只用于一个客户机的服务器实现

TCP是一种双向通信协议,因此,当然,您可以在需要时发送所需内容,同时接收任何内容

我试着在源代码中添加注释,让它自己解释

但关键点是将
TcpClient
NetworkStream
实例声明为静态变量,以便主线程(从控制台读取并将负载发送到客户端的线程)可以访问它们

希望这有帮助

public static async Task getMessage(TcpListener server)
{
    byte[] bytes = new byte[256];
    using (theStream = await server.AcceptTcpClientAsync())
    {
        using (tcpStream = theStream.GetStream())
        {
            // We are using an infinite loop which ends when zero bytes have been received.
            // Receiving zero bytes means the transmission is over (client disconnected)
            while (await tcpStream.ReadAsync(bytes, 0, bytes.Length) > 0)
            {
                var msg = Encoding.UTF8.GetString(bytes);
                Console.WriteLine(msg);
            }
            Console.WriteLine("Client has disconnected");
        }
    }
}

/// <summary>
/// Transmists the payload to the client
/// </summary>
/// <param name="payload">The payload to transmit to the client</param>
/// <returns></returns>
static async Task Transmit(string payload)
{
    var bytes2 = Encoding.UTF8.GetBytes(payload);
    await tcpStream.WriteAsync(bytes2, 0, bytes2.Length);
}

// We are declaring the TcpClient and NetworkStream as static variables
// to be able to access them from all the threads.
private static TcpClient theStream;
public static NetworkStream tcpStream;

static void Main(string[] args)
{
    TcpListener server = new TcpListener(IPAddress.Loopback, 9876);
    server.Start();

    // Start the task getMessage() to accept a client and receive
    Task.Run(() => getMessage(server));

    string payload;
    while ((payload = Console.ReadLine()) != "exit")
    {
        // Check if the client has connected.
        if (tcpStream != null)
        {
            // Check if they are still connected
            if (theStream.Client.Connected)
            {
                Task.Run(() => Transmit(payload));
            }
            else
            {
                Console.WriteLine("the client connection is lost");
                break;
            }
        }
        else
        {
            Console.WriteLine("The client has not connected yet.");
        }
    }

    Console.WriteLine("Stopping the server");
    server.Stop();
}
公共静态异步任务getMessage(TcpListener服务器)
{
字节[]字节=新字节[256];
使用(theStream=await server.AcceptTcpClientAsync())
{
使用(tcpStream=theStream.GetStream())
{
//我们使用的是一个无限循环,它在接收到零字节时结束。
//接收零字节表示传输结束(客户端断开连接)
while(等待tcpStream.ReadAsync(bytes,0,bytes.Length)>0)
{
var msg=Encoding.UTF8.GetString(字节);
控制台写入线(msg);
}
Console.WriteLine(“客户端已断开”);
}
}
}
/// 
///将有效负载传输到客户端
/// 
///要传输到客户端的有效负载
/// 
静态异步任务传输(字符串有效负载)
{
var bytes2=Encoding.UTF8.GetBytes(有效负载);
等待tcpStream.WriteAsync(字节2,0,字节2.Length);
}
//我们将TcpClient和NetworkStream声明为静态变量
//能够从所有线程访问它们。
私有静态TCP客户端流;
公共静态网络流;
静态void Main(字符串[]参数)
{
TcpListener服务器=新的TcpListener(IPAddress.Loopback,9876);
server.Start();
//启动任务getMessage()以接受客户端并接收
运行(()=>getMessage(服务器));
管柱有效载荷;
而((payload=Console.ReadLine())!=“退出”)
{
//检查客户端是否已连接。
if(tcpStream!=null)
{
//检查它们是否仍然连接
if(theStream.Client.Connected)
{
运行(()=>传输(有效负载));
}
其他的
{
Console.WriteLine(“客户端连接丢失”);
打破
}
}
其他的
{
Console.WriteLine(“客户端尚未连接”);
}
}
Console.WriteLine(“停止服务器”);
server.Stop();
}

我认为人们对您的帖子评价较低,因为您试图将多个响应从服务器发送回客户端,这是有问题的。客户机是主机,服务器是从机。所以,通常您会让客户端发送命令,服务器确认(可选),服务器进程命令,服务器发送响应。如果客户端发送多条消息,则您需要为每条消息发送一个ID,这样服务器就可以使用该ID进行响应,以便客户端知道哪个响应与每个命令关联。您使用的是两层网络1)应用程序层2)TCP传输层。亲爱的@jdweng,TCP不是面向请求/响应的协议。它是一个真正的双向异步通信协议,允许并发读/写。如果你说的是真的,那么玩一个像PUBG这样的游戏会消耗比必要的更多的网络资源,并且会带来延迟。想想你的PUBG客户不断询问所有其他玩家的所有动作和动作。这不是为多人实时动作游戏编程通信的有效方法。您所说的对于HTTP这样的无状态协议是正确的。@Oguz Ozgul:我确切地知道TCP是如何运行的,并且已经使用了40年。您必须定义一个应用层协议。对于聊天应用程序,双向异步协议是可以接受的。但在命令和控制应用程序中决不能使用双向异步。服务器是一个从服务器。还有其他一些协议可以通过TCP实现,比如令牌环。但这一点变得越来越复杂,我们需要这样做。