Princípios fundamentais
Depois que a conexão TCP é estabelecida, os dados são transmitidos por meio do NetworkStream (fluxo de rede);
A rede só consegue trafegar arrays de bytes byte[]. Textos precisam ser convertidos para bytes antes do envio e decodificados de volta para string no recebimento.
A transmissão não se limita apenas a textos. Arquivos e imagens também podem ser convertidos em arrays de bytes para serem enviados. Nesta seção vamos implementar primeiro um bate‑papo de texto.
Explicação das APIs importantes
- Lado do servidor
listener.AcceptTcpClient()
- Método de bloqueio (espera suspensa): a thread fica parada nesse ponto até que um cliente inicie uma conexão;
- Retorna um objeto
TcpClientque representa essa conexão com o cliente; - Recuperamos o fluxo de rede com
tcpClient.GetStream().
- Leitura e gravação no fluxo de rede
stream.Write(array de bytes, posição inicial, comprimento): Enviar dadosstream.Read(array buffer, posição inicial, comprimento máximo de leitura): Receber dados, devolve o número real de bytes lidos
- Avisos sobre codificação
Os exemplos do curso utilizamEncoding.Unicode(UTF‑16). O emissor e o receptor devem usar a mesma codificação, caso contrário ocorrerão caracteres ilegíveis.
Servidor WinForms
Controles:textBoxIP, textBoxPort, textBoxInfo (caixa de mensagens)
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)
Cliente WinForms
Controles:textBoxIP, textBoxPort, textBoxInfo, textBoxInput (caixa 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);
}
}
}Code language: PHP (php)
O código acima realiza o envio de mensagens entre cliente e servidor.
Comunicação entre cliente e servidor