【问题标题】:Receive multiple different messages TcpListener C#接收多个不同的消息 TcpListener C#
【发布时间】:2014-01-31 01:35:18
【问题描述】:

大家好,我一直在尝试学习如何使用 TcpListener 和套接字在客户端服务器之间发送一些简单的文本消息。我已经阅读了许多似乎显示如何读取 _Buffer 的线程,比如说一个循环以确保读取整个消息。但是,在收到第一条消息后,我似乎无法弄清楚如何获取第二条消息。我可以很好地连接到服务器,并且可以很好地收到第一条消息。但是,如果我再次点击客户端上的发送按钮,则不会有消息到达服务器。这是我的代码:

// 服务器应用程序: ------------------------------------------ -----

命名空间 TCP_Server { 公共部分类Form1:表格 { 公共表格1() { 初始化组件(); }

    private void btnStartServer_Click(object sender, EventArgs e)
    {
        // Define the TCP Listner:
        TcpListener _listner = new TcpListener(IPAddress.Parse("127.0.0.1"), 7777);

        // Start The Listner:
        _listner.Start();

        //Show the server is now listening:
        listStatus.Items.Add("Server started - Listening on port 7777");

        //Create a socket to accept - This is a Blocking Call:
        Socket _sock = _listner.AcceptSocket();

        //When Client Connects show server has accepted the socket:
        listStatus.Items.Add("User from IP " + _sock.RemoteEndPoint);

        while (_sock.Connected)
        {

            // Create Byte to Receive Data:
            byte[] _Buffer = new byte[1024];

            // Create integer to hold how large the Data Received is:
            int _DataReceived = _sock.Receive(_Buffer);

            // Lets Server Know Message is Received:
            listStatus.Items.Add("Message Received...");

            // Convert Buffer to a String:
            string _Message = Encoding.ASCII.GetString(_Buffer);

            // Post Message to the Server Window:
            listStatus.Items.Add(_Message);

            _sock.Close();
        }
    }
}

}

// 客户端应用程序: --------------------------------------------------------- -------

命名空间 TCP__Client { 公共部分类Form1:表格 { 公共表格1() { 初始化组件(); }

// 定义 TCP 客户端: TcpClient _Client = new TcpClient(); 私人无效btnConnect_Click(对象发送者,EventArgs e) { // 连接 TCP 客户端: _Client.Connect("127.0.0.1", 7777); // 显示客户端已连接: listStatus.Items.Add("连接到服务器 127.0.0.1"); } 私人无效btnSend_Click(对象发送者,EventArgs e) { 而(_Client.Connected) { // 创建一个流: 流 _Stream = _Client.GetStream(); // 创建编码器的实例: ASCIIEncoding _Asc = new ASCIIEncoding(); 字节[] _Buffer = 新字节[1024]; // 创建缓冲区以发送消息: _Buffer = _Asc.GetBytes(txtMessage.Text); // 显示客户端正在发送消息: listStatus.Items.Add("正在发送消息..."); // 将消息写入流: _Stream.Write(_Buffer, 0, _Buffer.Length); // 关闭流 _Stream.Close(); _Stream.Dispose(); } } }

}

如果有人能解释如何制作这个,我将不胜感激,这样我就可以获得不止一条消息。我在使用任务和线程方面确实有一点经验,这是我需要做的吗?我只是想掌握这一点,这样我就可以开始学习了。如果有人有任何您认为可以帮助的建议或示例,请分享。

【问题讨论】:

  • 在循环结束时不关闭套接字将是一个好的开始。如果关闭套接字,您如何期望获得更多字节?另请注意:“字节”不是“消息”。单独的 TCP 不能传输超过一个字节的“消息”。

标签: c# multithreading sockets tcp chat


【解决方案1】:

当客户端仍然连接到服务器时,不要故意关闭服务器应用程序上的套接字。由于您必须保持连接才能接收另一条消息,因此重复接收函数调用。如果客户端没有发送数据,Receive() 函数调用会自动阻塞当前线程等待可用数据。如果您再次单击客户端应用程序上的发送消息,数据将可供服务器使用,并将解除服务器应用程序上的阻塞部分。

您的服务器应用程序可能会阻塞 AcceptSocket() 和 Receive() 部分上的 UI 线程。单击 StartServer 按钮时,您的服务器窗口 (UI) 可能会因为没有可用的传入连接而没有响应,并且您在 listStatus 控件上看不到消息。因此,最好将这些 Socket 代码放在单独的线程上运行,以免阻塞 UI 线程。要从单独的线程处理 UI 组件,需要进行线程安全的 UI 操作。

这是我所做的更改:

服务器

namespace Tcp_Server
{
    public partial class Form1 : Form
    {
        delegate void AddTextCallback(string text);

        public Form1()
        {
            InitializeComponent();
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(ServerHandler));
        }

        private void ServerHandler(object args)
        {
            TcpListener _listner = new TcpListener(IPAddress.Parse("127.0.0.1"), 7777);

            // Start The Listner:
            _listner.Start();

            //Show the server is now listening (Note: UI Thread-Safe is required):
            AddText("Server started - Listening on port 7777");

            //Create a socket to accept - This is a Blocking Call:
            Socket _sock = _listner.AcceptSocket();

            //When Client Connects show server has accepted the socket:
            AddText("User from IP " + _sock.RemoteEndPoint);

            while (_sock.Connected)
            {

                // Create Byte to Receive Data:
                byte[] _Buffer = new byte[1024];

                // Create integer to hold how large the Data Received is:
                int _DataReceived = _sock.Receive(_Buffer);

                if (_DataReceived == 0)
                {
                    // Socket has been shutdown by the client.
                    break;
                }

                // Lets Server Know Message is Received:
                AddText("Message Received...");

                // Convert Buffer to a String:
                string _Message = Encoding.ASCII.GetString(_Buffer);

                // Post Message to the Server Window:
                AddText(_Message);
            }

            _sock.Close();
            //When Client disconnect from the server:
            AddText("Client Disconnected.");

            _listner.Stop();
            AddText("Server Stop.");
        }


        private void AddText(string text)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (this.listStatus.InvokeRequired)
            {
                AddTextCallback d = new AddTextCallback(AddText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.listStatus.Items.Add(text);
            }
        }
    }
}

客户

namespace Tcp_Client
{
    public partial class Form1 : Form
    {
        // Defind the TCP Client:
        TcpClient _Client = null;
        Stream _Stream = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            _Client = new TcpClient();

            // Connect the TCP Client:
            _Client.Connect("127.0.0.1", 7777);

            // Show the Client has Connected:
            listStatus.Items.Add("Connected to Server 127.0.0.1");

            // Create a Stream:                
            _Stream = _Client.GetStream();
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (_Client.Connected)
            {
                // Create Instance of an Encoder:
                ASCIIEncoding _Asc = new ASCIIEncoding();

                byte[] _Buffer = new byte[1024];

                // Create Buffer to Send Message:
                _Buffer = _Asc.GetBytes(txtMessage.Text);

                // Show Client is Sending Message:
                listStatus.Items.Add("Tranmitting Message...");

                // Write Message to the Stream:
                _Stream.Write(_Buffer, 0, _Buffer.Length);
            }
        }

        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            _Stream.Close();
            _Stream.Dispose();
            _Client.Close();
            listStatus.Items.Add("Disconnected from server.");
        }
    }
}

【讨论】:

  • 完美的工作太棒了......更好的是,我什至明白你在说什么哈哈。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-17
  • 1970-01-01
  • 1970-01-01
  • 2016-10-15
  • 2018-04-29
  • 2012-01-14
相关资源
最近更新 更多