【问题标题】:C# Multi threaded ServerC# 多线程服务器
【发布时间】:2015-08-11 18:28:44
【问题描述】:

我有这个客户端和服务器代码。 客户:

namespace ClientTest
{
internal class Program
{
private static TcpClient client;
private static NetworkStream stream;
private static void Main(string[] args)
{
string temp;
client = new TcpClient("192.168.1.2",5052);
stream = client.GetStream();
Console.WriteLine(client.SendBufferSize);
while ((temp = Console.ReadLine()) != "exit")
{
Send(temp);
}

Thread one=new Thread(()=> SendFile(new FileInfo(@"1.doc")));
one.Start();
Thread two=new Thread(()=> SendFile(new FileInfo(@"2.docx")));
two.Start();
// Console.ReadKey(true);
}

public static void SendFile(FileInfo file)
{
stream = client.GetStream();
byte[] id = BitConverter.GetBytes((ushort)1);
byte[] size = BitConverter.GetBytes(file.Length);
byte[] fileName = Encoding.UTF8.GetBytes(file.Name);
byte[] fileNameLength = BitConverter.GetBytes((ushort)fileName.Length);
byte[] fileInfo = new byte[12 + fileName.Length];

id.CopyTo(fileInfo, 0);
size.CopyTo(fileInfo, 2);
fileNameLength.CopyTo(fileInfo, 10);
fileName.CopyTo(fileInfo, 12);

stream.Write(fileInfo, 0, fileInfo.Length); //Размер файла, имя

byte[] buffer = new byte[1024 * 32];
int count;

long sended = 0;

using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open))
while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, count);
sended += count;
Console.WriteLine("{0} bytes sended.", sended);
}
stream.Flush();
}

private static void Send(string message)
{
byte[] id = BitConverter.GetBytes((ushort)0);
 byte[] msg = Encoding.UTF8.GetBytes(message);
 byte[] msgLength = BitConverter.GetBytes((ushort)msg.Length);
 byte[] fileInfo = new byte[12 + msg.Length];

 id.CopyTo(fileInfo, 0);
 msgLength.CopyTo(fileInfo, 10);
 msg.CopyTo(fileInfo, 12);
 stream.Write(fileInfo, 0, fileInfo.Length);
 stream.Flush();

}
}
}

服务器:

namespace Server_Test
{
class Server
{
    static void Main(string[] args)
    {
        Server serv = new Server();
    }
    private TcpListener listener { get; set; }
    private NetworkStream stream { get; set; }

    public Server()
    {
        listener = new TcpListener(IPAddress.Parse("192.168.1.2"), 5052);
        listener.Start();
        new Thread(ListenForClients).Start();
    }

    private void ListenForClients()
    {
        while (true)
        {
            TcpClient client = this.listener.AcceptTcpClient();
            new Thread(HandleClient).Start(client);
        }
    }

    private void HandleClient(object tcpClient)
    {
        TcpClient client = (TcpClient)tcpClient;
        while (client.Connected)
        {

            Recieve(client);
        }
    }

    private void Recieve(TcpClient client)
    {
        byte[] buffer = new byte[client.ReceiveBufferSize];
        try
        {
            stream = client.GetStream();
            int bytesRead = stream.Read(buffer, 0, 12);
            if (bytesRead == 0) return;

            ushort id = BitConverter.ToUInt16(buffer, 0);
            long len = BitConverter.ToInt64(buffer, 2);
            ushort nameLen = BitConverter.ToUInt16(buffer, 10);
            stream.Read(buffer, 0, nameLen);
            string fileName = Encoding.UTF8.GetString(buffer, 0, nameLen);

            if (id == 1)
            {
                using (BinaryWriter writer = new BinaryWriter(new     FileStream(fileName, FileMode.Create)))
                {
                    int recieved = 0;
                    while (recieved < len)
                    {
                        bytesRead = stream.Read(buffer, 0, client.ReceiveBufferSize);
                        recieved += bytesRead;
                        writer.Write(buffer, 0, bytesRead);
                        Console.WriteLine("{0} bytes recieved.", recieved);
                    }
                }
                Console.WriteLine("File length: {0}", len);
                Console.WriteLine("File Name: {0}", fileName);
                Console.WriteLine("Recieved!");
            }
            else
            {
                Console.WriteLine(fileName);
            }
        }
        catch (Exception ex)
        {

            stream.Close();
            client.Close();
            Console.WriteLine(ex);
        }
        finally
        {
            stream.Flush();
        }
    }
}
}

问题:我无法在线程中发送 2 个文件。如果我发送 1 个文件,服务器会收到它并正确保存。 此代码需要进行哪些更改才能让客户端传输 2 个或更多文件并让服务器接收它? UDP。添加了修改过的 SendFile,但是 in 不起作用。

public static void SendFile(FileInfo file)
    {
        TcpClient client;
        NetworkStream stream;
        client = new TcpClient("192.168.1.2", 5052);
        stream = client.GetStream();
        byte[] id = BitConverter.GetBytes((ushort)1);
        byte[] size = BitConverter.GetBytes(file.Length);
        byte[] fileName = Encoding.UTF8.GetBytes(file.Name);
        byte[] fileNameLength = BitConverter.GetBytes((ushort)fileName.Length);
        byte[] fileInfo = new byte[12 + fileName.Length];

        id.CopyTo(fileInfo, 0);
        size.CopyTo(fileInfo, 2);
        fileNameLength.CopyTo(fileInfo, 10);
        fileName.CopyTo(fileInfo, 12);

        stream.Write(fileInfo, 0, fileInfo.Length); //Размер файла, имя

        byte[] buffer = new byte[1024 * 32];
        int count;

        long sended = 0;

        using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open))
            while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                stream.Write(buffer, 0, count);
                sended += count;
                Console.WriteLine("{0} bytes sended.", sended);
            }
    }

【问题讨论】:

  • 您不能同时在一个流上发送两个不同的文件。您需要建立 2 个连接或按顺序发送文件。
  • 那么,我需要对这段代码进行哪些更改?
  • SendFile 方法应该创建TcpClient,而不是Main 方法。每个发送方法都需要有自己的连接。
  • 好的,谢谢,在服务器端它应该可以工作吗?
  • 我没有看到服务器端无法正常工作的任何问题,但这只是粗略的阅读。

标签: c# multithreading sockets tcp server


【解决方案1】:

在客户端,您的两个单独的发送线程不能共享client = new TcpClient("192.168.1.2",5052); 的同一实例来同时发送数据。每个线程都应该有自己的实例。但是请注意,两个客户端套接字可以同时访问同一个服务器端 IP:port。只是客户端的出站端口在两个连接之间必须不同。当您在客户端上创建额外的出站 TCP 连接时,TcpClient 将自动使用下一个可用的出站端口。

例如,您可以尝试以下操作:

internal class Program
{
private static void Main(string[] args)
{
    SenderThreadClass stc1 = SenderThreadClass("192.168.1.2", 5052);
    SenderThreadClass stc2 = SenderThreadClass("192.168.1.2", 5052);
    Thread one = new Thread(()=> stc1.SendFile(new FileInfo(@"1.doc")));
    one.Start();
    Thread two = new Thread(()=> stc2.SendFile(new FileInfo(@"2.docx")));
    two.Start();
}
}

public class SenderThreadClass
{
private TcpClient client;
private NetworkStream stream;

public SenderThreadClass(string serverIP, int serverPort)
{
   client = new TcpClient(serverIP, serverPort);
   stream = client.GetStream();
}

public void SendFile(FileInfo file)
{
byte[] id = BitConverter.GetBytes((ushort)1);
byte[] size = BitConverter.GetBytes(file.Length);
byte[] fileName = Encoding.UTF8.GetBytes(file.Name);
byte[] fileNameLength = BitConverter.GetBytes((ushort)fileName.Length);
byte[] fileInfo = new byte[12 + fileName.Length];

id.CopyTo(fileInfo, 0);
size.CopyTo(fileInfo, 2);
fileNameLength.CopyTo(fileInfo, 10);
fileName.CopyTo(fileInfo, 12);

stream.Write(fileInfo, 0, fileInfo.Length); //Размер файла, имя

byte[] buffer = new byte[1024 * 32];
int count;
long sended = 0;

using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open))
while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, count);
sended += count;
Console.WriteLine("{0} bytes sended.", sended);
}
stream.Flush();
}
}

【讨论】:

  • 我刚刚制作了一些示例代码。这不是经过编译检查的代码,因为我面前没有 IDE,但它应该为您提供有关如何继续的正确想法。
  • 我试过了,但是 in 不起作用。你知道可能的原因吗?
  • 在服务器端,private NetworkStream stream { get; set; } 成员应该被删除,而是在 private void Recieve(TcpClient client) { } 函数中作为局部变量实例化。例如,您可以向该函数添加新的第一行:NetworkStream stream;
  • 好的,我做到了,但我应该写下一个stream=client.getstream()吗?
  • 看起来该语句出现在try { } 块内的第一行,因此无需执行两次。
猜你喜欢
  • 2017-01-22
  • 1970-01-01
  • 1970-01-01
  • 2011-08-06
  • 2019-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多