Principios básicos
Una vez establecida la conexión TCP, los datos circulan a través de NetworkStream (flujo de red);
La red solo trabaja con arreglos de bytes byte[]. El texto debe codificarse previamente a bytes y, al recibirlo, se decodifica para reconstruir la cadena original.
No solo se transmite texto: también archivos e imágenes se pueden convertir a arreglos de bytes para enviarse. En esta sección primero implementamos un chat de texto.
Explicación de las API principales
- Lado del servidor
listener.AcceptTcpClient()
- Método de bloqueo (espera suspendida): el hilo se detiene en esta línea hasta que algún cliente solicite una conexión;
- Devuelve un objeto
TcpClientque representa esa conexión de cliente; - Obtenemos el flujo de red mediante
tcpClient.GetStream().
- Lectura y escritura sobre el flujo de red
stream.Write(arreglo de bytes, posición inicial, longitud): Enviar datosstream.Read(arreglo búfer, posición inicial, longitud máxima de lectura): Recibir datos, retorna la cantidad real de bytes leídos
- Consideraciones sobre la codificación
Los ejemplos del curso usanEncoding.Unicode(UTF‑16). El emisor y el receptor deben usar exactamente la misma codificación, si no aparecerán caracteres corruptos.
Servidor WinForms
Controles:textBoxIP, textBoxPort, textBoxInfo (cuadro de mensajes)
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;
}
}
}Lenguaje del código: PHP (php)
Cliente WinForms
Controles:textBoxIP, textBoxPort, textBoxInfo, textBoxInput (cuadro de entrada)buttonStart【Conectar】, buttonSend【Enviar】
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);
}
}
}Lenguaje del código: PHP (php)
Este código implementa el envío de mensajes entre cliente y servidor.
Comunicación entre cliente y servidor