核心原理
TCP建立连接之后,依靠 NetworkStream(网络流) 传输数据;
网络只能传输字节数组byte[],文本需要先编码成字节,接收后再解码还原字符串。
传输不限于文本,文件、图片同样可以转为字节数组传输,本节先实现文本聊天。
关键API说明
- 服务端
listener.AcceptTcpClient()
- 阻塞方法(中断等待):执行到这里线程暂停,直到有客户端发起连接;
- 返回
TcpClient对象,代表这条客户端连接; - 通过
tcpClient.GetStream()获取网络流。
- 网络流读写
stream.Write(字节数组,起始位置,长度):发送数据stream.Read(缓存数组,起始位置,最大读取长度):接收数据,返回读到的实际字节长度
- 编码注意
课程示例使用Encoding.Unicode(UTF-16),收发两端编码必须保持一致,否则乱码。
服务端 WinForms
控件:textBoxIP、textBoxPort、textBoxInfo(消息框)
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
控件:textBoxIP、textBoxPort、textBoxInfo、textBoxInput(输入框)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)
以上代码实现了,客户端和服务器端之间信息的发送。