套接字停止接收新数据

时间:2014-06-03 15:48:48

标签: c# wpf multithreading sockets

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

没有进一步的麻烦:

情况如下 我有一个桌面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;
            }
        }

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。 代码工作正常,但是连接有问题。

需要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;
        }));

希望这可以帮助其他任何人遇到这个问题。