Socket停止接收新数据

本文关键字:数据 新数据 Socket | 更新日期: 2023-09-27 18:06:33

在我开始解释我的问题之前,我必须说我在网络/套接字方面缺乏经验(可能是我遇到麻烦的原因的解释)

废话少说:

情况如下我有一个桌面WPF应用程序,它必须使用套接字从服务器接收不断的数据流。目前不需要发送任何数据,只需要接收部分。我目前有2个线程。第一个用于运行应用程序并进行任何GUI更新,第二个用于从套接字接收任何数据并通过委托将其传递给我的GUI线程。

由于某种原因,它第一次接收到数据,然后停止获取新数据,只输出第一次接收到的相同字符串。

下面的代码是MSDN的例子,稍微调整以适应我的需要。

     // State object for receiving data from remote device.
    public class StateObject {
    // Client socket.
    public Socket workSocket = null;
    // Size of receive buffer.
    public const int BufferSize = 256;
    // Receive buffer.
    public byte[] buffer = new byte[BufferSize];
    // Received data string.
    public StringBuilder sb = new StringBuilder();
    }
public class AsynchronousClient {
    // The port number for the remote device.
    private const int port = 2003;
    static Socket currentsocket;
    static int packetsreceived = 0;
    // ManualResetEvent instances signal completion.
    private static ManualResetEvent connectDone = 
        new ManualResetEvent(false);
    private static ManualResetEvent sendDone = 
        new ManualResetEvent(false);
    private static ManualResetEvent receiveDone = 
        new ManualResetEvent(false);
    // The response from the remote device.
    private static String response = String.Empty;

    public static void StartClient() {

        // Connect to a remote device.
        try {
            // Establish the remote endpoint for the socket.
            // ip adress : xx.xx.xx.xxx
            IPHostEntry ipHostInfo = Dns.GetHostEntry(IPAddress.Parse("xx.xx.xx.xxx"));
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
            // Create a TCP/IP socket.
            Socket client = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);
            currentsocket = client;

            // Send test data to the remote device.
            //Send(client,"This is a test<EOF>");
            //sendDone.WaitOne();
            // Connect to the remote endpoint.
            client.BeginConnect(remoteEP,
                new AsyncCallback(ConnectCallback), client);
            connectDone.WaitOne();
            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                ((MainWindow)Application.Current.MainWindow).socketconnected = true;
                ((MainWindow)Application.Current.MainWindow).loadingimage.Visibility = Visibility.Hidden;
                ((MainWindow)Application.Current.MainWindow).statuslabel.Content = "Connected";
                ((MainWindow)Application.Current.MainWindow).statuslabel.Foreground = System.Windows.Media.Brushes.Green;
            }));
            // Receive the responses from the remote device.
            // main loop of receiving
            while (true)
            {
                if (!client.Connected)
                {
                    client.BeginConnect(remoteEP,
                    new AsyncCallback(ConnectCallback), client);
                    connectDone.WaitOne();
                }
                if (client.Connected)
                {
                    Receive(client);
                    receiveDone.WaitOne();
                    packetsreceived++;
                    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        ((MainWindow)Application.Current.MainWindow).packetslabel.Content = packetsreceived;
                        ((MainWindow)Application.Current.MainWindow).panel.Text += response;
                    }));
                    Thread.Sleep(1000);
                    // Release the socket.
                    //client.Shutdown(SocketShutdown.Both);
                    //client.Close();
                }
            }

        } catch (Exception e) {
            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                ((MainWindow)Application.Current.MainWindow).socketconnected = false;
                ((MainWindow)Application.Current.MainWindow).connectbutton.Content = "Connect";
                ((MainWindow)Application.Current.MainWindow).loadingimage.Visibility = Visibility.Hidden;
                ((MainWindow)Application.Current.MainWindow).statuslabel.Content = "Disconnected";
                ((MainWindow)Application.Current.MainWindow).statuslabel.Foreground = System.Windows.Media.Brushes.Red;
            }));
        }
    }
private static void Receive(Socket client) {
        try {
            // Create the state object.
            StateObject state = new StateObject();
            state.workSocket = client;
            // Begin receiving the data from the remote device.
            client.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReceiveCallback), state);
        } catch (Exception e) {
            Console.WriteLine(e.ToString());
        }
    }
    private static void ReceiveCallback( IAsyncResult ar ) {
        try {
            // Retrieve the state object and the client socket 
            // from the asynchronous state object.
            StateObject state = (StateObject) ar.AsyncState;
            Socket client = state.workSocket;
            // Read data from the remote device.
            int bytesRead = client.EndReceive(ar);
            if (bytesRead > 0) {
                // There might be more data, so store the data received so far.
            state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));
                // Get the rest of the data.
                client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
                    new AsyncCallback(ReceiveCallback), state);
            } else {
                // All the data has arrived; put it in response.
                if (state.sb.Length > 1) {
                    response = state.sb.ToString();
                }
                // Signal that all bytes have been received.
                receiveDone.Set();
            }
        } catch (Exception e) {
            Console.WriteLine(e.ToString());
        }
    }
public static int Main(String[] args)
{
        StartClient();
}

最后在我的主线程:

// starts the socket thread and starts recieving
        private void connectbutton_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (!socketconnected)
            {
                statuslabel.Content = "Connecting..";
                loadingimage.Visibility = Visibility.Visible;
                // socket stuff
                    socketThread = new Thread(new ThreadStart(() =>
                    {
                        AsynchronousClient.Main(new string[0]);
                        // Start the Dispatcher Processing
                        System.Windows.Threading.Dispatcher.Run();
                    }));
                    // Set the apartment state
                    socketThread.SetApartmentState(ApartmentState.STA);
                    // Make the thread a background thread
                    socketThread.IsBackground = true;
                // Start the thread
                socketThread.Start();
                connectbutton.Content = "Disconnect";
            }
            else
            {
                socketThread.Abort();
                socketconnected = false;
            }
        }

Socket停止接收新数据

我找到了解决办法。代码工作正常,但是,有一个连接问题。

需要Thread.Sleep()来确保它正确连接到套接字。我通过调试这部分代码发现了这一点,并发现当我跳过代码时,它没有获得新数据,但是当我跳过所有代码时,它确实收到了新数据。

我是这样解决的:

// Connect to a remote device.
    try {
        // Establish the remote endpoint for the socket.
        // ip adress : xx.xx.xx.xxx
        IPHostEntry ipHostInfo = Dns.GetHostEntry(IPAddress.Parse("xx.xx.xx.xxx"));
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
        // Create a TCP/IP socket.
        Socket client = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);
        currentsocket = client;

        // Send test data to the remote device.
        //Send(client,"This is a test<EOF>");
        //sendDone.WaitOne();
        // Connect to the remote endpoint.
        client.BeginConnect(remoteEP,
            new AsyncCallback(ConnectCallback), client);
        connectDone.WaitOne();
        Thread.sleep(250);
        Application.Current.Dispatcher.BeginInvoke(new Action(() =>
        {
            ((MainWindow)Application.Current.MainWindow).socketconnected = true;
            ((MainWindow)Application.Current.MainWindow).loadingimage.Visibility = Visibility.Hidden;
            ((MainWindow)Application.Current.MainWindow).statuslabel.Content = "Connected";
            ((MainWindow)Application.Current.MainWindow).statuslabel.Foreground = System.Windows.Media.Brushes.Green;
        }));