客户端与服务器通信

核心原理

TCP建立连接之后,依靠 NetworkStream(网络流) 传输数据;
网络只能传输字节数组byte[],文本需要先编码成字节,接收后再解码还原字符串。

传输不限于文本,文件、图片同样可以转为字节数组传输,本节先实现文本聊天。

关键API说明

  1. 服务端
    listener.AcceptTcpClient()
  • 阻塞方法(中断等待):执行到这里线程暂停,直到有客户端发起连接;
  • 返回TcpClient对象,代表这条客户端连接;
  • 通过 tcpClient.GetStream() 获取网络流。
  1. 网络流读写
  • stream.Write(字节数组,起始位置,长度)发送数据
  • stream.Read(缓存数组,起始位置,最大读取长度)接收数据,返回读到的实际字节长度
  1. 编码注意
    课程示例使用 Encoding.Unicode(UTF-16),收发两端编码必须保持一致,否则乱码。

服务端 WinForms

控件:
textBoxIPtextBoxPorttextBoxInfo(消息框)

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace TcpServer
{
    public partial class Form1 : Form
    {
        IPAddress ip;
        TcpListener listener;
        TcpClient tcpClient;

        public Form1()
        {
            InitializeComponent();
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            ip = IPAddress.Parse(textBoxIP.Text);
            listener = new TcpListener(ip, Convert.ToInt32(textBoxPort.Text));
            listener.Start();

            textBoxInfo.Text = $"服务器启动-{DateTime.Now.ToShortTimeString()}\r\n" + textBoxInfo.Text;

            // 阻塞!主线程卡住
            tcpClient = listener.AcceptTcpClient();
            textBoxInfo.Text = $"连接成功-{DateTime.Now.ToShortTimeString()}\r\n" + textBoxInfo.Text;

            NetworkStream stream = tcpClient.GetStream();
            byte[] byteArray = new byte[1024];

            // 阻塞等待客户端发送消息
            int length = stream.Read(byteArray, 0, 1024);
            string receiveMessage = Encoding.Unicode.GetString(byteArray, 0, length);

            textBoxInfo.Text = $"接收到:{receiveMessage}-{DateTime.Now.ToShortTimeString()}\r\n" + textBoxInfo.Text;
        }
    }
}Code language: PHP (php)

客户端 WinForms

控件:
textBoxIPtextBoxPorttextBoxInfotextBoxInput(输入框)
buttonStart【连接】、buttonSend【发送】

using System;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace TcpClientChat
{
    public partial class Form1 : Form
    {
        TcpClient tcpClient;

        public Form1()
        {
            InitializeComponent();
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            tcpClient = new TcpClient();
            try
            {
                tcpClient.Connect(textBoxIP.Text, Convert.ToInt32(textBoxPort.Text));
                textBoxInfo.AppendText("连接成功!\r\n");
            }
            catch (Exception ex)
            {
                MessageBox.Show("连接失败-" + ex.Message);
            }
        }

        private void buttonSend_Click(object sender, EventArgs e)
        {
            string message = textBoxInput.Text;
            textBoxInfo.Text = $"发送“{message}”-{DateTime.Now.ToShortTimeString()}\r\n" + textBoxInfo.Text;

            NetworkStream stream = tcpClient.GetStream();
            byte[] byteArray = Encoding.Unicode.GetBytes(message);
            stream.Write(byteArray, 0, byteArray.Length);
        }
    }
}Code language: PHP (php)

以上代码实现了,客户端和服务器端之间信息的发送。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注