简体   繁体   中英

Cannot start a simple TCP/IP client

I'm trying to open a TCP/IP listener but when I run the code below, it crashes. It doesn't give me an error because when it crashes, it freezes and stops responding.

TcpListener server = new TcpListener(IPAddress.Any, 619);
TcpClient client;

private void button3_Click(object sender, EventArgs e)
{
    server.Start();
    client = server.AcceptTcpClient();

    if (client.Connected)
    {
        MessageBox.Show("connected");
    }
}

I know for a fact this port is free so that's not it. it crashes on this line:

client = server.acceptTcpClient();

This is expected behaviour. Your program hasn't crashed - the call to AccpetTcpClient() blocks waiting for an incoming connection:

https://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.accepttcpclient(v=vs.110).aspx

You need to also open a TCP connection to port 619 from another thread, then your program will continue to run.

AcceptTcpClient is a blocking method

( https://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.accepttcpclient%28v=vs.110%29.aspx ).

When you call AcceptTcpClient, it will wait until a connection is made. Because it waits on the main thread (where also the GUI is running on), it will look like the program is frozen. Try using AcceptTcpClientAsync or putting the accepting part in a different thread. That should solve your problem.

Desirius

You're executing a blocking call on the UI thread which gives the appearance of a "Crashing" application.

You need to use another thread or do things asynchronously. Background worker might be a starting point.

private BackgroundWorker bgw = new BackgroundWorker();

public MainWindow()
{
    InitializeComponent();
    bgw.DoWork += Bgw_DoWork;
    bgw.RunWorkerCompleted += Bgw_RunWorkerCompleted;
    bgw.WorkerSupportsCancellation = true;
}

private void button3_Click(object sender, EventArgs e)
{
    if (!bgw.IsBusy)
    {
        bgw.RunWorkerAsync();
        ((Button)sender).Content = "Cancel";
    }
    else
    {
        bgw.CancelAsync();
    }
}

private void Bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    button.Content = "Start";
}

private void Bgw_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    var server = new TcpListener(IPAddress.Any, 619);
    server.Start();
    while (true)
    {
        if (worker.CancellationPending)
        {
            e.Cancel = true;
            server.Stop();
            break;
        }
        else
        {
            if (server.Pending())
            {
                var client = listener.AcceptTcpClient();
                // handle client here or do something like below to return the client to the RunWorkerCompleted method in 
                // e.result
                e.Result = client;
                break;
            }
        }
    }
}

There are other options such as using server.AcceptTcpClientAsync() instead of polling the server.Pending() property. Also, polling in this way without using Thread.Sleep in between may be overkill, ie, you're checking the property very frequently and wasting cycles.

Following all of that, you need to figure out a way to deal with the client in a way that makes sense for your application. One click per client accepted? Handle new connections forever as they arrive until you cancel the listener? Etc. Good luck

BackgroundWorker tutorial

AcceptTcpClientAsync MSDN

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM