0

我是 C# 多线程的新手,我从以下在线教程中遇到了这个问题

这是我的服务器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Configuration;
using System.Threading;

namespace CoreEngine
{
    class MultithreadedTCP
    {
        private TcpListener myListener;
        private Thread ListenThread;

    public MultithreadedTCP()
    {
        IPAddress ip = IPAddress.Parse(ConfigurationManager.AppSettings["CoreEngineIP"]);
        myListener = new TcpListener(ip, Convert.ToInt32(ConfigurationManager.AppSettings["CoreEnginePort"]));
        this.ListenThread = new Thread(new ThreadStart(ListenForClients));
        this.ListenThread.Start();
    }

    private void ListenForClients()
    {
        this.myListener.Start();

        while (true)
        {
            TcpClient client = this.myListener.AcceptTcpClient();
            Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
            clientThread.Start(client);
        }
    }

    private void HandleClientComm(object client)
    {
        TcpClient Tcpclient = (TcpClient)client;
        NetworkStream clientStream = Tcpclient.GetStream();
        byte[] message = new byte[4096];
        while (true)
        {
            //send all data here
            clientStream.Read(message, 0, message.Length);
            Console.WriteLine("client connected : " + Encoding.UTF8.GetString(message, 0, message.Length));
            //break;
        }

    }
}

}

这是我的客户代码。我刺激了 4 个客户端连接到这个服务器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Configuration;
using System.Configuration.Assemblies;
namespace WindowsFormsApplication1
{
    class Client
    {
        public void send(String args)
        {
            TcpClient tcp = new TcpClient();
            TcpClient tcp1 = new TcpClient();
            TcpClient tcp2 = new TcpClient();
            TcpClient tcp3 = new TcpClient();
            tcp.Connect(ConfigurationManager.AppSettings["CoreEngineIP"], Convert.ToInt32(ConfigurationManager.AppSettings["CoreEnginePort"]));
            tcp1.Connect(ConfigurationManager.AppSettings["CoreEngineIP"], Convert.ToInt32(ConfigurationManager.AppSettings["CoreEnginePort"]));
            tcp2.Connect(ConfigurationManager.AppSettings["CoreEngineIP"], Convert.ToInt32(ConfigurationManager.AppSettings["CoreEnginePort"]));
            tcp3.Connect(ConfigurationManager.AppSettings["CoreEngineIP"], Convert.ToInt32(ConfigurationManager.AppSettings["CoreEnginePort"]));

            args = "client 0";
            Stream str = tcp.GetStream();
            ASCIIEncoding asen = new ASCIIEncoding();
            byte[] b = asen.GetBytes(args);
            str.Write(b, 0, b.Length);

            args = "client 1";
            Stream str1 = tcp1.GetStream();
            ASCIIEncoding asen1 = new ASCIIEncoding();
            byte[] b1 = asen.GetBytes(args);
            str.Write(b1, 0, b.Length);

            args = "client 2";
            Stream str2 = tcp2.GetStream();
            ASCIIEncoding asen2 = new ASCIIEncoding();
            byte[] b2 = asen.GetBytes(args);
            str.Write(b2, 0, b.Length);

            args = "client 3";
            Stream str3 = tcp3.GetStream();
            ASCIIEncoding asen3 = new ASCIIEncoding();
            byte[] b3 = asen.GetBytes(args);
            str.Write(b3, 0, b.Length);
        }
    }
}

输出:客户端已连接:客户端 0 客户端 1 客户端 2 客户端 3

预期输出:客户端连接:客户端 0 客户端连接:客户端 1 客户端连接:客户端 2 客户端连接:客户端 3

4

1 回答 1

1

您调用str.Write每个块中的第一个客户端。

然而,这表明了您没有考虑的第二个问题,Read(即没有读取相同数量Write(的电汇。所有 4 条连接消息都合并为一个Read.

您需要开发某种形式的“消息协议”来表示一条消息在哪里停止和开始。最简单的方法是在发送消息之前添加消息的长度。

客户端

args = "client 0";
Stream str = tcp.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] b = asen.GetBytes(args);
if(b.Length > 255)
    throw new InvalidDataException("Messages must have a length less than 256");
str.WriteByte((byte)b.Length);
str.Write(b, 0, b.Length);

服务器端

byte[] message = new byte[256]; //This can now be 256 as that is the most messageLength can be.
while (true)
{
    //get the length of the message
    int messageLength = clientStream.ReadByte();
    if(messageLength == -1)
        break;

    // "Read(" can read less than the total length you requested, so you must loop till you have the entire message.
    int offset = 0;
    while(offset < messageLength)
    {
        offset += clientStream.Read(message, offset, messageLength - offest);
    }
    Console.WriteLine("client connected : " + Encoding.UTF8.GetString(message, 0, message.Length));
}

如果你想发送大于 255 字节的消息,你可以,但你需要围绕它设计协议。例如,您可以str.Write(BitConverter.GetBytes(b.Length), 0, 4)从客户端写入网络流并读取消息的前 4 个字节,然后调用,但是当您开始使用多字节数字时,您int messageLength = BitConverter.ToInt32(message)需要开始担心字节顺序。BitConverter.IsLittleEndian总是true在 Windows 桌面上返回,但在移动平台上可能会有所不同)

于 2013-11-10T02:18:57.123 回答