C# WPF服务器应用程序

C# WPF服务器应用程序,c#,wpf,sockets,client-server,C#,Wpf,Sockets,Client Server,我有一个WPF服务器和客户端应用程序。 当我启动服务器时,它开始监听传入的消息。但是,应用程序不能被触摸或关闭,它被“卡住”了。我必须补充一点,它在处理消息等方面做了它应该做的事情,但我就是不能与表单交互。 它与异步服务器套接字有关吗?我不知道该找什么 这是我的服务器代码: private void startServer() { sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, Pro

我有一个WPF服务器和客户端应用程序。 当我启动服务器时,它开始监听传入的消息。但是,应用程序不能被触摸或关闭,它被“卡住”了。我必须补充一点,它在处理消息等方面做了它应该做的事情,但我就是不能与表单交互。 它与异步服务器套接字有关吗?我不知道该找什么

这是我的服务器代码:

    private void startServer()
    {
        sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        sck.Bind(new IPEndPoint(0, serverPort));
        sck.Listen(100);

        while (true)
        {
            Socket accepted = sck.Accept();

            Buffer = new byte[accepted.SendBufferSize];
            int bytesRead = accepted.Receive(Buffer);

            byte[] formatted = new byte[bytesRead];

            for (int i = 0; i < bytesRead; i++)
            {
                formatted[i] = Buffer[i];
            }
            string command = Encoding.ASCII.GetString(formatted);
            string[] splittedCommand = command.Split(' ');

            jobsHistory.Items.Add(Encoding.ASCII.GetString(formatted));
            jobsHistory.Refresh();

            Process processToRun = new Process();
            processToRun.StartInfo.FileName = splittedCommand[0];
            processToRun.StartInfo.WorkingDirectory = Path.GetDirectoryName(splittedCommand[0]);
            processToRun.StartInfo.Arguments = "";
            for (int i = 1; i < splittedCommand.Length; i++)
            {
                processToRun.StartInfo.Arguments += " " + splittedCommand[i];
            }

            processToRun.Start();
            accepted.Close();
        }
    }
private void startServer()
{
sck=新套接字(AddressFamily.InterNetwork、SocketType.Stream、ProtocolType.Tcp);
绑定(新的IPEndPoint(0,serverPort));
听(100);
while(true)
{
接受套接字=sck.Accept();
Buffer=新字节[accepted.SendBufferSize];
int bytesRead=accepted.Receive(缓冲区);
字节[]格式化=新字节[字节读取];
for(int i=0;i
如果这在UI线程上起作用,那么您就是在循环中绑定它。它没有机会处理任何UI事件。除此之外,
Socket.Receive
是一个阻塞调用


在这个网站和谷歌上都有很多关于BackgroundWorker类的文章。我建议你研究一下这些问题。

只需在一个单独的线程中执行监听,就像这样-

    private void startServer()
    {
        sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        sck.Bind(new IPEndPoint(0, 8080));

        new Thread(() => StartListening(sck)).Start();
    }

    void StartListening(Socket socket)
    {
        socket.Listen(100);

        Accept(socket);
    }

    void Accept(Socket socket)
    {
        while (true)
        {
            Socket accepted = socket.Accept();

            Buffer = new byte[accepted.SendBufferSize];
            int bytesRead = accepted.Receive(Buffer);

            byte[] formatted = new byte[bytesRead];

            for (int i = 0; i < bytesRead; i++)
            {
                formatted[i] = Buffer[i];
            }
            string command = Encoding.ASCII.GetString(formatted);
            string[] splittedCommand = command.Split(' ');

            jobsHistory.Items.Add(Encoding.ASCII.GetString(formatted));
            jobsHistory.Refresh();

            Process processToRun = new Process();
            processToRun.StartInfo.FileName = splittedCommand[0];
            processToRun.StartInfo.WorkingDirectory = Path.GetDirectoryName(splittedCommand[0]);
            processToRun.StartInfo.Arguments = "";
            for (int i = 1; i < splittedCommand.Length; i++)
            {
                processToRun.StartInfo.Arguments += " " + splittedCommand[i];
            }

            processToRun.Start();
            accepted.Close();
        }

        // If you want to start listening again
        socket.Close();
        startServer();
    }
private void startServer()
{
sck=新套接字(AddressFamily.InterNetwork、SocketType.Stream、ProtocolType.Tcp);
sck.Bind(新的IPEndPoint(08080));
新线程(()=>StartListening(sck)).Start();
}
无效侦听(套接字)
{
听(100);
接受(插座);
}
无效接受(套接字)
{
while(true)
{
接受套接字=Socket.Accept();
Buffer=新字节[accepted.SendBufferSize];
int bytesRead=accepted.Receive(缓冲区);
字节[]格式化=新字节[字节读取];
for(int i=0;i
您应该使用
beginacept
在后台接受连接,而不阻塞UI线程。当客户机被接受时,再次调用
beginacept
——这将创建一个“循环”。您可以在循环时删除

startServer
方法可能如下所示:

private void startServer()
{
    sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    sck.Bind(new IPEndPoint(0, serverPort));
    sck.Listen(100);

    sck.BeginAccept(Accepted, sck);
}
然后,在接受的
方法中,执行以下操作:

private void Accepted(IAsyncResult result)
{
    Socket sck = result.AsyncState as Socket;
    Socket client = sck.EndAccept(result);

    sck.BeginAccept(Accepted, sck);
}


        Socket accepted = sck.Accept();

首先,谢谢你的回复。现在可以了。但是,如果我连接,然后断开连接,然后再次重新连接,就会抛出一个异常,说:“每个套接字地址(协议/网络地址/端口)通常只允许使用一次”.@Idanis这可能是因为您执行操作太快,而套接字实际上尚未释放。请尝试关闭
套接字
,然后再次调用
startServer
。。。请参阅我的更新以了解
Accept
方法…我修改了代码。我只是想展示一下大局。我有一个“监听”按钮,当插座监听时,它会变为“断开”,反之亦然。如你所见,我添加了更改,但现在我无法断开连接或重新连接…我在这里遗漏了什么?谢谢…我认为你应该就你的连接/断开问题提出一个新问题,在那里很有可能得到答案。同时,如果此答案解决了您的原始问题,请将其标记为答案,以便对其他ppl搜索相同问题有所帮助。