Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.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# 服务器(GUI)在启动后冻结。在控制台中工作正常_C#_Multithreading_Server_Client - Fatal编程技术网

C# 服务器(GUI)在启动后冻结。在控制台中工作正常

C# 服务器(GUI)在启动后冻结。在控制台中工作正常,c#,multithreading,server,client,C#,Multithreading,Server,Client,服务器(GUI) using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; usi

服务器(GUI)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;

namespace Server_ProfiChat
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        static readonly object _lock = new object();
        static readonly Dictionary<int, TcpClient> list_clients = new Dictionary<int, TcpClient>();


        public static void handle_clients(object o)
        {
            int id = (int)o;
            TcpClient client;

            lock (_lock) client = list_clients[id];

            while (true)
            {
                NetworkStream stream = client.GetStream();
                byte[] buffer = new byte[1024];
                int byte_count = stream.Read(buffer, 0, buffer.Length);

                if (byte_count == 0)
                {
                    break;
                }

                string data = Encoding.ASCII.GetString(buffer, 0, byte_count);
                broadcast(data);
                Console.WriteLine(data);
                //var chatline = txtChat.Text;
                Form1 formObj = new Form1();
                formObj.txtChat.Text += data;
            }

            lock (_lock) list_clients.Remove(id);
            client.Client.Shutdown(SocketShutdown.Both);
            client.Close();
        }

        public static void broadcast(string data)
        {
            byte[] buffer = Encoding.ASCII.GetBytes(data + Environment.NewLine);

            lock (_lock)
            {
                foreach (TcpClient c in list_clients.Values)
                {
                    NetworkStream stream = c.GetStream();

                    stream.Write(buffer, 0, buffer.Length);
                }
            }
        }








        private void btnConnect_Click(object sender, EventArgs e)
        {
            int count = 1;

            string serverIP = txtServerIP.Text;
            int serverPort = Int32.Parse(txtServerPort.Text);

            TcpListener ServerSocket = new TcpListener(IPAddress.Parse(serverIP), serverPort);
            ServerSocket.Start();

            while (true)
            {
                TcpClient client = ServerSocket.AcceptTcpClient();
                lock (_lock) list_clients.Add(count, client);
                Console.WriteLine("Someone connected!!");

                Thread t = new Thread(handle_clients);
                t.Start(count);
                count++;
            }
        }
    }
}

我是一个初学者,但对我来说,这似乎和线程有关? 另外,因为它冻结了,我看不出其余部分是否正常工作,有没有关于如何改进工作流程的想法,比如寻找错误的确切位置?我在搜索任何东西上浪费了很多时间,因为我不知道如何正确地测试、调试和找出我犯的错误


感谢所有帮助=)

流通常完全按照您的要求执行。如果您请求10个字节,则在有10个字节可返回之前,
Read
不会返回。
stream.Read
不会返回更少的字节,因为这是接收到的字节数

此代码将一直阻塞,直到读取1024个字节

byte[] buffer = new byte[1024];
int byte_count = stream.Read(buffer, 0, buffer.Length);
if (byte_count == 0)
{
     break;
}
这就是你所期待的吗

通常,基于字节的协议有一个标头,其中包含有效负载中的字节数

想象一下下面的协议:

  • stx=开始传输
  • soh=收割台的开始
  • len=有效载荷的长度
  • eoh=收割台末端
  • etx=传输结束
要读取完整的数据包,必须读取4个字节,然后必须读取足够的字节以完成有效负载,最后一个字节应为ETX

byte[5] header;
stream.Read(buffer, 0, 4);

int payloadLength = header[2];
byte[] payload = new byte[payloadLength];
stream.Read(payload, 0, payloadLength);
stream.Read() == ETX;
方法是阻塞。您可以尝试使用其异步对应项,并结合使用:


在控制台中运行需要多长时间?表单将被锁定相同的时间。为了防止在表单应用程序中锁定,您必须在BackGroundWorker中运行代码。(或异步任务)。我是一个初学者,但对我来说,这似乎和线程有关?回答:是的。尤其是在使用UI线程。它正在等待连接。不要使用
lock/Dictionary
,而是使用
ConcurrentDictionary
,它可以完成您尝试执行的操作,但效果更好。
byte[] buffer = new byte[1024];
int byte_count = stream.Read(buffer, 0, buffer.Length);
if (byte_count == 0)
{
     break;
}
byte[5] header;
stream.Read(buffer, 0, 4);

int payloadLength = header[2];
byte[] payload = new byte[payloadLength];
stream.Read(payload, 0, payloadLength);
stream.Read() == ETX;
private async void btnConnect_Click(object sender, EventArgs e)
{
    /* ... */
    TcpClient client = await ServerSocket.AcceptTcpClientAsync();
    /* ... */
}