套接字连接发送一条消息但不再发送

Socket connection sends one message but not anymore

我正在尝试一个关于套接字连接的基本项目。我创建了以下表格:

任务很简单。我将从左边发送消息,然后从右边接收消息。

我的代码如下:

private bool _senderStarted = false;
private bool _listenerStarted = false;

private Socket sListener;
private ManualResetEvent listenerNotifier = new ManualResetEvent(false);

private Socket sSender;
private IPEndPoint senderEndpoint = null;

public Form1()
{
    InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
    // Create sockets
    sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    sSender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
private void btnSenderStart_Click(object sender, EventArgs e)
{
    _senderStarted = true;
    btnSenderStart.Enabled = false;
    btnSenderStop.Enabled = true;
    txtMessage.Enabled = true;
    btnSend.Enabled = true;
    txtMessage.Clear();
    txtMessage.Focus();
    lstSender.Items.Clear();
     // Create sender endpoint
    string[] arr = txtSenderIP.Text.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
    byte[] ips = arr.Select(x => byte.Parse(x)).ToArray();
    IPAddress senderAddress = new IPAddress(ips);
    senderEndpoint = new IPEndPoint(senderAddress, (int)txtSenderPort.Value);
    sSender.Connect(senderEndpoint);
}
private void btnListenerStart_Click(object sender, EventArgs e)
{
    _listenerStarted = true;
    btnListenerStart.Enabled = false;
    btnListenerStop.Enabled = true;
    lstListener.Items.Clear();
    // Create listener endpoint
    string[] arr = txtListenerIP.Text.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
    byte[] ips = arr.Select(x => byte.Parse(x)).ToArray();
    IPAddress listenerAddress = new IPAddress(ips);
    IPEndPoint listenerEndpoint = new IPEndPoint(listenerAddress, (int)txtSenderPort.Value);
    // Bind listener to endpoint
    sListener.Bind(listenerEndpoint);
    bwListener.RunWorkerAsync();
}
private void btnSenderStop_Click(object sender, EventArgs e)
{
    _senderStarted = false;
    btnSenderStart.Enabled = true;
    btnSenderStop.Enabled = false;
    txtMessage.Enabled = false;
    btnSend.Enabled = false;
    txtMessage.Clear();
}
private void btnListenerStop_Click(object sender, EventArgs e)
{
    _listenerStarted = false;
    btnListenerStart.Enabled = true;
    btnListenerStop.Enabled = false;
}
#region Listener
private void AcceptCallback(IAsyncResult ar)
{
    // Signal the main thread to continue.
    listenerNotifier.Set();
    // Get the socket that handles the client request.
    Socket listener = (Socket)ar.AsyncState;
    Socket handler = listener.EndAccept(ar);
    // Create the state object.
    StateObject listenerState = new StateObject();
    listenerState.workSocket = handler;
    handler.BeginReceive(listenerState.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), listenerState);
}
public void ReadCallback(IAsyncResult ar)
{
    String content = String.Empty;
    // Retrieve the state object and the handler socket from the asynchronous state object.
    StateObject state = (StateObject)ar.AsyncState;
    Socket handler = state.workSocket;

    // Read data from the client socket. 
    int bytesRead = handler.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));
        // Check for end-of-file tag. If it is not there, read more data.
        content = state.sb.ToString();

        this.Invoke(new MethodInvoker(delegate()
        {
            lstListener.Items.Add(content);
        }));
    }
}
#endregion

private void btnSend_Click(object sender, EventArgs e)
{
    byte[] byteData = Encoding.ASCII.GetBytes(txtMessage.Text);
    sSender.Send(byteData);
    txtMessage.Clear();
    txtMessage.Focus();
}

private void bwListener_DoWork(object sender, DoWorkEventArgs e)
{
    sListener.Listen(10);
     while (_listenerStarted)
    {
        // Set the event to nonsignaled state.
        listenerNotifier.Reset();
        // Start an asynchronous socket to listen for connections.
        sListener.BeginAccept(new AsyncCallback(AcceptCallback), sListener);
        // Wait until a connection is made before continuing.
        listenerNotifier.WaitOne();
    }
}

如图所示,我可以成功发送消息。但是当我尝试发送第二条消息时,似乎发送消息的侦听器根本没有收到任何消息。我缺少什么,或者我应该修复什么?

此致。

您没有启动后续接收操作。第一个完成后,您的代码不会尝试接收更多数据。如果您在处理完给定的接收操作后再次调用 BeginReceive(),您应该会成功读取更多数据。

例如:

public void ReadCallback(IAsyncResult ar)
{
    String content = String.Empty;
    // Retrieve the state object and the handler socket from the asynchronous state object.
    StateObject state = (StateObject)ar.AsyncState;
    Socket handler = state.workSocket;

    // Read data from the client socket. 
    int bytesRead = handler.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));
        // Check for end-of-file tag. If it is not there, read more data.
        content = state.sb.ToString();

        this.Invoke(new MethodInvoker(delegate()
        {
            lstListener.Items.Add(content);
        }));

        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
    }
}

(顺便说一句:我最近看到许多问题都遵循与您正在使用的代码类似的风格——命名约定、class 设计、逻辑流程等. – 这让我相信这些都是从某个地方的一个通用代码示例派生出来的。不幸的是,它并不是一个很好的网络实现 I/O。我希望我知道这些示例是从哪里来的......这很好请参阅上下文中的原始代码示例)。