C#多线程文件传输使用TCP

标签 c# sockets tcp tcpclient tcplistener

我正在设计用于从客户端接收文件的 TCP 服务器。它为一个客户工作。但是Server需要响应多个client。我不知道如何同时从客户端接收多个文件。请帮助我。

服务器代码:

public partial class Form1 : Form
{
    Thread t1;
    int flag = 0;
    string receivedPath = "yok";
    public delegate void MyDelegate();
    private string fileName;
    public Form1()
    {
        t1 = new Thread(new ThreadStart(StartListening));
        t1.Start();
        InitializeComponent();
    }


    public class StateObject
    {
        // Client socket.
        public Socket workSocket = null;

        public const int BufferSize = 8096;
        // Receive buffer.
        public byte[] buffer = new byte[BufferSize];
    }

    public static ManualResetEvent allDone = new ManualResetEvent(true);

    public void StartListening()
    {
        byte[] bytes = new Byte[8096];
        IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
        Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        try
        {
            listener.Bind(ipEnd);
            listener.Listen(100);
            SetText("Listening For Connection");
            while (true)
            {
                allDone.Reset();
                listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                allDone.WaitOne();

            }
        }
        catch (Exception ex)
        {
        }

    }

    public void AcceptCallback(IAsyncResult ar)
    {
        allDone.Set();

        Socket listener = (Socket)ar.AsyncState;
        Socket handler = listener.EndAccept(ar);

        StateObject state = new StateObject();
        state.workSocket = handler;
        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
        flag = 0;

    }

    public void ReadCallback(IAsyncResult ar)
    {
        int fileNameLen = 1;
        String content = String.Empty;
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.workSocket;
        int bytesRead = handler.EndReceive(ar);
        if (bytesRead > 0)
        {
            if (flag == 0)
            {
                fileNameLen = BitConverter.ToInt32(state.buffer, 0);
                fileName = Encoding.UTF8.GetString(state.buffer, 4, fileNameLen);
                receivedPath = @"D:\" + fileName;
                flag++;
            }

            if (flag >= 1)
            {
                BinaryWriter writer = new BinaryWriter(File.Open(receivedPath, FileMode.Append));
                if (flag == 1)
                {
                    writer.Write(state.buffer, 4 + fileNameLen, bytesRead - (4 + fileNameLen));
                    flag++;
                }
                else
                writer.Write(state.buffer, 0, bytesRead);
                writer.Close();
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
            }
        }
        else
        {
            Invoke(new MyDelegate(LabelWriter));
        }

    }
    public void LabelWriter()
    {
       label1.Text = "Data has been received " + fileName;
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
        t1.Abort();
    }


}

客户端代码:

  public partial class Form1 : Form
    {
        string splitter = "'\\'";
        string fName;
        string[] split = null;
        byte[] clientData;

        public Form1()
        {
            InitializeComponent();
            button2.Visible = false;
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            char[] delimiter = splitter.ToCharArray();
            //openFileDialog1.ShowDialog();
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                textBox1.Text = openFileDialog1.FileName;
                textBox2.AppendText("Selected file " + textBox1.Text);
                button2.Visible = true;
            }
            else
            {
                textBox2.AppendText("Please Select any one file to send");
                button2.Visible = false;
            }

            split = textBox1.Text.Split(delimiter);
            int limit = split.Length;
            fName = split[limit - 1].ToString();
            if (textBox1.Text != null)
                button1.Enabled = true;
        }

        private void button2_Click_1(object sender, EventArgs e)
        {
            Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //IPAddress ip = new IPAddress;


            byte[] fileName = Encoding.UTF8.GetBytes(fName); //file name
            byte[] fileData = File.ReadAllBytes(textBox1.Text); //file
            byte[] fileNameLen = BitConverter.GetBytes(fileName.Length); //lenght of file name
            clientData = new byte[4 + fileName.Length + fileData.Length];

            fileNameLen.CopyTo(clientData, 0);
            fileName.CopyTo(clientData, 4);
            fileData.CopyTo(clientData, 4 + fileName.Length);

            textBox2.AppendText("Preparing File To Send");
            clientSock.Connect("127.0.0.1", 9050); //target machine's ip address and the port number
            clientSock.Send(clientData);
            //clientSock.
            clientSock.Close();

        }


    }
}

最佳答案

使用异步操作自然会使用IO线程池,并发操作。只允许接受并具有每个连接的状态管理(例如接收缓冲区)。

我还建议将用于通信的工作人员代码与任何 UI 代码完全分开(大多数服务器预计无需登录即可运行)。

关于C#多线程文件传输使用TCP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9326649/

相关文章:

c# - 使用Linq构建图类;你能让这段代码看起来更好吗?

c# - xmlns :dc mean in C# WPF? 是什么

javascript - 如何防止使用Socket.io滚动类似事件? - Angular 7

windows - Golang、net.TCPConn、SetReadTimeout?

c# - 使用变量作为循环的终点 - C#

c# - 以编程方式自动化 Web 登录

c++ - boost asio async_read 延迟(本地套接字)

javascript - 将 socket.io 与 Express 4 生成器一起使用

Java TCP 服务器套接字在不同端口上接受多个客户端

networking - IP数据包在接收方有尾部,但在发送方没有