Nguyên Tắc Mạng Cơ Sở
Các thành phần cốt lõi bao gồm địa chỉ IP, cổng kết nối và địa chỉ MAC. Địa chỉ IP xác định thiết bị trên mạng, cổng kết nối định tuyến lưu lượng đến ứng dụng cụ thể. Thư viện System.Net cung cấp lớp IPAddress và IPEndPoint để quản lý thông tin kết nối:
// Khởi tạo điểm kết nối
var serverAddress = IPAddress.Parse("10.1.5.20");
var connectionPoint = new IPEndPoint(serverAddress, 7777);
Phân Giải Tên Miền
Lớp Dns thực hiện chuyển đổi tên miền thành địa chỉ IP. Kết quả trả về qua IPHostEntry chứa danh sách địa chỉ và thông tin máy chủ:
async Task ResolveDomainAsync()
{
var hostInfo = await Dns.GetHostEntryAsync("api.example.com");
foreach (var ip in hostInfo.AddressList)
{
Debug.Log($"Địa chỉ IP: {ip}");
}
Debug.Log($"Tên máy chủ: {hostInfo.HostName}");
}
Giao Tiếp Socket TCP
Máy chủ:
var listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Any, 7777));
listener.Listen(5);
// Chấp nhận kết nối không đồng bộ
var clientSocket = await listener.AcceptAsync();
// Gửi phản hồi
var response = Encoding.UTF8.GetBytes("Kết nối thành công!");
await clientSocket.SendAsync(response);
// Nhận dữ liệu
var buffer = new byte[1024];
var received = await clientSocket.ReceiveAsync(buffer);
Debug.Log(Encoding.UTF8.GetString(buffer, 0, received));
Máy khách:
var client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
try
{
await client.ConnectAsync("10.1.5.20", 7777);
// Gửi yêu cầu
var request = Encoding.UTF8.GetBytes("Yêu cầu dữ liệu");
await client.SendAsync(request);
// Xử lý phản hồi
var result = new byte[2048];
var count = await client.ReceiveAsync(result);
Debug.Log(Encoding.UTF8.GetString(result, 0, count));
}
catch (SocketException ex) when (ex.ErrorCode == 10061)
{
Debug.LogError("Máy chủ chưa sẵn sàng");
}
Xử Lý Gói Tin
Vấn đề dính gói (packet sticking) và phân mảnh (fragmentation) được giải quyết bằng cơ chế đệm vòng lặp:
private byte[] _buffer = new byte[8192];
private int _bufferPosition;
private void ProcessIncomingData(byte[] data, int length)
{
Array.Copy(data, 0, _buffer, _bufferPosition, length);
_bufferPosition += length;
int index = 0;
while (_bufferPosition - index >= 4)
{
int packetLength = BitConverter.ToInt32(_buffer, index);
index += 4;
if (_bufferPosition - index >= packetLength)
{
byte[] packet = new byte[packetLength];
Array.Copy(_buffer, index, packet, 0, packetLength);
HandlePacket(packet);
index += packetLength;
}
else
{
// Giữ lại dữ liệu chưa xử lý
Array.Copy(_buffer, index - 4, _buffer, 0, _bufferPosition - index + 4);
_bufferPosition = _bufferPosition - index + 4;
break;
}
}
}
Giao Thức UDP Cơ Bản
Giao tiếp không kết nối với độ trễ thấp:
// Máy chủ
var udpServer = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);
udpServer.Bind(new IPEndPoint(IPAddress.Any, 9999));
var remoteEp = new IPEndPoint(IPAddress.Any, 0);
var receivedData = udpServer.ReceiveFrom(new byte[512], ref remoteEp);
Debug.Log($"Nhận từ {remoteEp}: {Encoding.UTF8.GetString(receivedData)}");
// Máy khách
var udpClient = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);
udpClient.SendTo(Encoding.UTF8.GetBytes("Ping"),
new IPEndPoint(IPAddress.Parse("10.1.5.20"), 9999));
Yêu Cầu HTTP Với UnityWebRequest
Tải tài nguyên từ máy chủ:
IEnumerator DownloadResource()
{
using var request = UnityWebRequest.Get("https://example.com/data.json");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
var jsonData = request.downloadHandler.text;
// Xử lý dữ liệu JSON
}
}
Sử Dụng Protobuf
Mô hình dữ liệu hiệu quả cho truyền tải mạng:
// File player.proto
syntax = "proto3";
package GameData;
message PlayerState {
int32 id = 1;
float x = 2;
float y = 3;
repeated string items = 4;
}
Sau khi biên dịch, sử dụng trong C#:
var state = new PlayerState { id = 101, x = 5.2f, y = 3.7f };
byte[] data = state.ToByteArray();
// Gửi qua mạng
socket.Send(data);
// Nhận và giải mã
var receivedState = PlayerState.Parser.ParseFrom(receivedBytes);