2

我试图解决这个问题以及调试,但我在这里处于松散的结局:(有没有其他方法可以使用它来检查客户端连接?这段代码在控制台应用程序中运行良好,所以我猜测线程被阻止了,虽然它可能是我看不到的其他东西?

public partial class Form1 : Form
{
    Socket s;

插座的声明。

private void startButton_Click(object sender, EventArgs e)
    {
        checkTimer.Enabled = true;
        if (bw.IsBusy != true)
        {
            bw.RunWorkerAsync();
        }
    }

按下按钮时启动的后台线程。

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
        BackgroundWorker worker = sender as BackgroundWorker;

        working();
}

线程运行“工作”方法。

 private void working()
 {
     if (threadFirstRun == true)
     {
            threadFirstRun = false;
     }

        try
        {

            String tempAddr = tbAddr.Text;
            IPAddress ipAd = IPAddress.Parse("147.197.204.172");
            // use local m/c IP address, and 
            // use the same in the client
            String tempPort = tbPort.Text;
            /* Initializes the Listener */
            TcpListener myList = new TcpListener(ipAd, 3000);

            /* Start Listeneting at the specified port */
            myList.Start();
            tcConnection1 = "Console:\n" + "The server is running at port 3000...";
            tcConnection2 = "\n" + "The local End point is  :" + myList.LocalEndpoint;
            tcConnection3 = "\n" + "Waiting for a connection.....";

            while (true)
            {
                s = myList.AcceptSocket();
                if (s != null)
                {
                    if (connectionEstab == false)
                    {
                        tcEstab = "\n" + "Connection accepted from " + s.RemoteEndPoint;
                        connectionEstab = true;
                    }


                    byte[] b = new byte[100];
                    int k = s.Receive(b);
                    //Console.WriteLine("Recieved...");
                    for (int i = 0; i < k; i++)
                    {
                        //Console.Write(Convert.ToChar(b[i]));
                        tcValue = tcValue + Convert.ToString(b[i]);
                        valueArray[ii] = (float)Convert.ToDouble(b[i]);
                    }
                    tcValue = tcValue + "\n";
                    ii++;
                }
                else
                {
                    Thread.Sleep(200);
                }
            }

            ASCIIEncoding asen = new ASCIIEncoding();
            s.Send(asen.GetBytes("The string was recieved by the server."));
            rtbConsole.Text = rtbConsole.Text + "\n" + "Sent Acknowledgement";
            /* clean up */
            s.Close();
            myList.Stop();
        }
        catch (Exception ex)
        {
            tcError = "\n\n" + "Error..... " + ex.StackTrace;
        }
}

工作方法在调用 myList.AcceptSocket(); 时启动服务器并阻塞?

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
        if ((e.Cancelled == true))
        {
            rtbConsole.Text = rtbConsole.Text + "\n" + "Canceled!";
        }

        else if (!(e.Error == null))
        {
            rtbConsole.Text = rtbConsole.Text + "\n\n" + ("Error: " + e.Error.Message);
        }

        else
        {
            rtbConsole.Text = rtbConsole.Text + "\n" + "Done!";
        }
}

private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
        rtbConsole.Text = rtbConsole.Text + "\n" + (e.ProgressPercentage.ToString() + "%");
}

private void stopButton_Click(object sender, EventArgs e)
{
        checkTimer.Enabled = false;
        if (bw.WorkerSupportsCancellation == true)
        {
            bw.CancelAsync();
        }
}

其他一些完整性的方法。

在解释我的问题时进行编辑:(

从我的 android 设备发送数据由运行 1 个线程的控制台应用程序接收,但是在从同一设备上的同一程序向同一 ip 和端口发送数据时,此 windows 窗体应用程序似乎没有发生任何事情。单独的线程只是保持阻塞状态,android 应用程序无法完成通信以发送数据。

4

2 回答 2

2

应该是阻塞的。它永远不能返回 null。(为什么每个人都这样做?就像网络上没有人正确使用 Accept 一样。)

您的问题是,在接受一个连接后,您处理该连接并且什么都不做来恢复接受。标准模式是:

while (true) {
 var connectionSocket = listeningSocket.Accept();
 ProcessAsynchronously(connectionSocket);
}

确保ProcessAsynchronously立即返回。开始一个新的Task或使用 async/await。

由于您永远不会退出 while 循环,因此您永远不会发送数据。将所有处理逻辑移入ProcessAsynchronously.

于 2014-07-10T16:09:47.947 回答
1

它应该阻止。来自MSDN

AcceptSocket 是一种阻塞方法,它返回一个可用于发送和接收数据的 Socket。如果要避免阻塞,请使用 Pending 方法来确定传入连接队列中是否有可用的连接请求。

您可以将整个实现转为使用异步版本:AcceptSocketAsync. 请注意,这不会阻止您的方法,它将控制权交还给调用者,直到Socket连接了新方法。

private async void bw_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    await WorkingAsync();
}

在里面WorkingAsync

private Task WorkingAsync
{
    // Do all other stuff,

    Socket socket = await myList.AcceptSocketAsync();

   // Do rest of stuff with the socket
}

我建议您喜欢ThreadPool 服务器的异步/等待等价物是什么?完整实现异步 tcp 连接处理程序

于 2014-07-10T15:50:26.060 回答