c# - 不允许发送或接收数据的请求,因为未连接套接字(仅当我第二次连接时)

标签 c# wpf sockets asynchronous tcpclient

我在理解C#tcp异步客户端程序时遇到了很大的问题!我已经编写了下一个代码(主要是从Microsoft开发人员网络开始的,我只将console.writeline更改为WPF应用程序的lambda表达式),这里的问题是我收到错误消息“不允许发送或接收数据的请求,因为没有套接字连接,并且(当使用发送调用在数据报套接字上发送时)未提供地址”!

我不介意应用程序在我第一次连接到服务器时是否向我显示消息,但是当我第二次连接时会出现此错误。 它说我没有提供地址,但是当我使用相同的地址连接时,为什么它第一次但第二次不起作用?

PS:我不认为问题出在服务器应用程序中,因为我检查了所有内容(与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 static int port;
    private static IPAddress ipAd;
    public static TextBlock statusPanel;

    // 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 setPort(int portt)
    {
        port = portt;
    }

    public static void setIpAddress(string ip)
    {
        ipAd = IPAddress.Parse(ip);
    }

    public static void setStatusPanel(TextBlock status)
    {
        statusPanel = status;
    }          

    public static void StartClient(string message)
    {
        // Connect to a remote device.
        try
        {
            // Establish the remote endpoint for the socket.
            IPAddress ipAddress = ipAd;
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

            // Create a TCP/IP socket.
            Socket client = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

            // Connect to the remote endpoint. IMPORTANT: AsyncCallback will be called on seperate thread
            client.BeginConnect(remoteEP,
                new AsyncCallback(ConnectCallback), client);
            connectDone.WaitOne();

            // Send test data to the remote device.
            string sendingMessage = message + "<EOF>";
            Send(client, sendingMessage);
            sendDone.WaitOne();

            // Receive the response from the remote device.
            Receive(client);
            receiveDone.WaitOne();

            // Write the response to the console.
            //statusPanel.Text += "Response received: " + response + "\n\n";

            // Release the socket.
            client.Shutdown(SocketShutdown.Both);
            client.Close();
        }
        catch (Exception e)
        {
            statusPanel.Dispatcher.BeginInvoke(new Action(() =>
                statusPanel.Text += e.ToString() + "\n"
               ));
        }
    }

    public static void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.
            Socket client = (Socket)ar.AsyncState;


            // Complete the connection.
            client.EndConnect(ar);

            //string remote = client.RemoteEndPoint.ToString();

          //  statusPanel.Dispatcher.BeginInvoke(new Action(() =>
            //    statusPanel.Text = "Message send to: " + remote + "\n"
             //  ));

            // Signal that the connection has been made.
            connectDone.Set();
        }
        catch (Exception e)
        {
            statusPanel.Dispatcher.BeginInvoke(new Action(() =>
                statusPanel.Text += e.ToString() + "\n"
               ));
        }
    }

    private static void Receive(Socket client)
    {
        try
        {
            // Create the state object.
            StateObject state = new StateObject();
            state.workSocket = client;

            // FOLLOWING LINE IS WHERE THE PROGRAM CHRASHES
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReceiveCallback), state);
        }
        catch (Exception e)
        {
            statusPanel.Dispatcher.BeginInvoke(new Action(() =>
                statusPanel.Text += e.ToString() + "\n"
               ));
        }
    }

    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)
        {
            statusPanel.Dispatcher.BeginInvoke(new Action(() =>
                statusPanel.Text += e.ToString() + "\n"
               ));
        }
    }

    private static void Send(Socket client, String data)
    {
        // Convert the string data to byte data using ASCII encoding.
        byte[] byteData = Encoding.ASCII.GetBytes(data);

        // Begin sending the data to the remote device.
        client.BeginSend(byteData, 0, byteData.Length, 0,
            new AsyncCallback(SendCallback), client);
    }

    private static void SendCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.
            Socket client = (Socket)ar.AsyncState;

            // Signal that all bytes have been sent.
            sendDone.Set();
        }
        catch (Exception e)
        {
            statusPanel.Dispatcher.BeginInvoke(new Action(() =>
                statusPanel.Text += e.ToString() + "\n"
               ));
        }
    }
}

最佳答案

由于连接事件在第一次连接后处于设置状态,因此第二次尝试在实际连接完成之前发送。 connectDone,sendDone和receiveDone是ManualResetEvent,您需要在开始第二次连接,发送和接收之前进行重置。

关于c# - 不允许发送或接收数据的请求,因为未连接套接字(仅当我第二次连接时),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25836658/

相关文章:

python - python 异常包含的 errnos 是否与 "linux/errno.h"中的 errnos 相同?

python - 从单个长字符串创建列表

php - 在 HandlerSocket 上基于原始套接字的查询中表示 NULL 键值的正确方法

c# - List 后面没有 <T> 怎么可能存在?

c# - WPF:异步进度条

c# - WebClient登录失败

WPF在单击复选框时传递多个参数

c# - 如何在 WinForms 应用程序中处理表单?

c# - 无法将 Xamarin.Android 和 Xamarin.iOS 添加到 PCL

c# - 需要在 C# 中使用字符串从数据库中查找 ID 号