You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复TCP聊天程序中的"未连接套接字不允许操作"错误?

问题:TCP聊天程序发送消息时出现“Operation not allowed on unconnected sockets”错误

为完成学校项目,开发客户端-服务器架构的桌面聊天应用,参考TCP Listener与TcpClient教程编写代码后,尝试发送消息时弹出该错误。

原代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace NetworkTest
{
    public partial class Form1 : Form
    {
        private TcpClient client;
        public StreamReader STR;
        public StreamWriter STW;
        public string recieve;
        public string TextToSend;
        public Form1()
        {
            InitializeComponent();
            IPAddress[] localIP = Dns.GetHostAddresses(Dns.GetHostName());

            foreach(IPAddress address in localIP)
            {
                if(address.AddressFamily == AddressFamily.InterNetwork)
                {
                    IPBox1.Text = address.ToString();
                }
            }
        }

        private void StartButton_Click(object sender, EventArgs e)
        {
            TcpListener listener = new TcpListener(IPAddress.Any, int.Parse(PortBox1.Text));
            listener.Start();
            client = listener.AcceptTcpClient();
            STR = new StreamReader(client.GetStream());
            STW = new StreamWriter(client.GetStream());
            STW.AutoFlush = true;
            backgroundWorker1.RunWorkerAsync();
            backgroundWorker2.WorkerSupportsCancellation = true;
        }

        private void ConnectButton_Click(object sender, EventArgs e)
        {
            client = new TcpClient();
            IPEndPoint IpEnd = new IPEndPoint(IPAddress.Parse(IPBox2.Text), int.Parse(PortBox2.Text));

            try
            {
                ChatScreenBox.AppendText("Connect to Server" + "\n");
                STW = new StreamWriter(client.GetStream());
                STR = new StreamReader(client.GetStream());
                STW.AutoFlush = true;
                backgroundWorker1.RunWorkerAsync();
                backgroundWorker2.WorkerSupportsCancellation = true;
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            while (client.Connected)
            {
                try
                {
                    recieve = STR.ReadLine();
                    this.ChatScreenBox.Invoke(new MethodInvoker(delegate ()
                    {
                        ChatScreenBox.AppendText("You: " + recieve + "\n");
                    }));
                recieve = "";
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message.ToString());
                }
            }
        }

        private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
            if (client.Connected)
            {
                STW.WriteLine(TextToSend);
                this.ChatScreenBox.Invoke(new MethodInvoker(delegate()
                {
                    ChatScreenBox.AppendText("Me: " + TextToSend + "\n");
                }));
            }
            else
            {
                MessageBox.Show("Sending Failed");
            }
            backgroundWorker2.CancelAsync();
        }

        private void SendButton_Click(object sender, EventArgs e)
        {
            if(MessageTextBox.Text != "")
            {
                TextToSend = MessageTextBox.Text;
                backgroundWorker2.RunWorkerAsync();
            }
            MessageTextBox.Text = "";
        }
    }
}

错误原因

  • 客户端未执行连接操作:在ConnectButton_Click方法中,创建TcpClient实例后,没有调用client.Connect(IpEnd)建立与服务器的连接,直接尝试获取套接字流,此时套接字处于未连接状态。
  • 流对象绑定未连接套接字:即使连接未建立,代码仍创建了StreamWriter和StreamReader,这些对象依赖未连接的套接字,发送消息时触发“不允许在未连接套接字上操作”的错误。
  • 连接状态校验不严谨:发送消息前未检查client是否已成功连接,仅判断消息非空就触发发送逻辑。

解决方案

1. 修复客户端连接逻辑

修改ConnectButton_Click方法,先执行连接操作,确认连接成功后再创建流对象:

private void ConnectButton_Click(object sender, EventArgs e)
{
    client = new TcpClient();
    IPEndPoint IpEnd = new IPEndPoint(IPAddress.Parse(IPBox2.Text), int.Parse(PortBox2.Text));

    try
    {
        // 先建立与服务器的连接
        client.Connect(IpEnd);
        ChatScreenBox.AppendText("已连接到服务器\n");
        
        // 连接成功后再初始化流
        STW = new StreamWriter(client.GetStream());
        STR = new StreamReader(client.GetStream());
        STW.AutoFlush = true;
        backgroundWorker1.RunWorkerAsync();
        backgroundWorker2.WorkerSupportsCancellation = true;
    }
    catch(Exception ex)
    {
        MessageBox.Show("连接失败:" + ex.Message);
    }
}

2. 增加发送前的连接校验

修改SendButton_Click方法,确保客户端已连接后再执行发送:

private void SendButton_Click(object sender, EventArgs e)
{
    string message = MessageTextBox.Text.Trim();
    if(!string.IsNullOrEmpty(message) && client != null && client.Connected)
    {
        TextToSend = message;
        backgroundWorker2.RunWorkerAsync();
    }
    else
    {
        MessageBox.Show("请先连接到服务器");
    }
    MessageTextBox.Text = "";
}

3. 优化资源释放(可选)

在窗体关闭时释放TCP资源,避免端口占用:

protected override void OnFormClosing(FormClosingEventArgs e)
{
    base.OnFormClosing(e);
    // 关闭客户端连接
    client?.Close();
    // 如果将TcpListener声明为类成员,此处也需停止
    // listener?.Stop();
}

内容的提问来源于stack exchange,提问作者Whole-Humor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 13:00:50