TCP-UDP-WebSocket-组播-单播
1. TCP 通信
TCP(Transmission Control Protocol):
特点:
面向连接,可靠传输。
保证数据顺序和完整性。
适用于需要可靠传输的场景(如文件传输、网页浏览)。
C 语言案例:
服务器端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0};
char *response = "Hello from server";
// 创建 socket
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket failed");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
// 绑定 socket
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
// 监听
if (listen(server_fd, 3) < 0) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
// 接受连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("Accept failed");
exit(EXIT_FAILURE);
}
// 读取数据
read(new_socket, buffer, BUFFER_SIZE);
printf("Client: %s\n", buffer);
// 发送响应
send(new_socket, response, strlen(response), 0);
printf("Response sent\n");
close(new_socket);
close(server_fd);
return 0;
}
客户端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sock = 0;
struct sockaddr_in serv_addr;
char *message = "Hello from client";
char buffer[BUFFER_SIZE] = {0};
// 创建 socket
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket creation error");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// 将 IP 地址从字符串转换为二进制
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
perror("Invalid address/ Address not supported");
return -1;
}
// 连接服务器
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("Connection Failed");
return -1;
}
// 发送数据
send(sock, message, strlen(message), 0);
printf("Message sent\n");
// 接收响应
read(sock, buffer, BUFFER_SIZE);
printf("Server: %s\n", buffer);
close(sock);
return 0;
}
2.UDP(User Datagram Protocol)
特点:
无连接,不可靠传输。
数据包可能丢失或乱序。
适用于实时性要求高的场景(如视频流、在线游戏)。
C 语言案例:
服务器端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sockfd;
char buffer[BUFFER_SIZE];
struct sockaddr_in servaddr, cliaddr;
// 创建 socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// 绑定 socket
if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
int len, n;
len = sizeof(cliaddr);
// 接收数据
n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);
buffer[n] = '\0';
printf("Client: %s\n", buffer);
// 发送响应
sendto(sockfd, "Hello from server", strlen("Hello from server"), MSG_CONFIRM, (const struct sockaddr *)&cliaddr, len);
printf("Response sent\n");
close(sockfd);
return 0;
}
客户端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sockfd;
char buffer[BUFFER_SIZE];
struct sockaddr_in servaddr;
// 创建 socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY;
// 发送数据
sendto(sockfd, "Hello from client", strlen("Hello from client"), MSG_CONFIRM, (const struct sockaddr *)&servaddr, sizeof(servaddr));
printf("Message sent\n");
// 接收响应
int len, n;
len = sizeof(servaddr);
n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, MSG_WAITALL, (struct sockaddr *)&servaddr, &len);
buffer[n] = '\0';
printf("Server: %s\n", buffer);
close(sockfd);
return 0;
}
3.WebSocket 通信
特点:
全双工通信协议,基于 TCP。
适用于实时通信场景(如聊天应用、实时数据推送)。
C 语言案例:
WebSocket 通常使用库(如 libwebsockets)实现,以下是一个简单示例:
#include <libwebsockets.h>
#include <stdio.h>
#include <string.h>
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
return 0;
}
static int callback_websocket(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
switch (reason) {
case LWS_CALLBACK_ESTABLISHED:
printf("Connection established\n");
break;
case LWS_CALLBACK_RECEIVE:
printf("Received data: %s\n", (char *)in);
lws_write(wsi, in, len, LWS_WRITE_TEXT);
break;
default:
break;
}
return 0;
}
static struct lws_protocols protocols[] = {
{ "http-only", callback_http, 0, 0 },
{ "websocket", callback_websocket, 0, 0 },
{ NULL, NULL, 0, 0 }
};
int main() {
struct lws_context_creation_info info;
struct lws_context *context;
memset(&info, 0, sizeof info);
info.port = 8080;
info.protocols = protocols;
context = lws_create_context(&info);
if (!context) {
fprintf(stderr, "WebSocket context creation failed\n");
return -1;
}
while (1) {
lws_service(context, 1000);
}
lws_context_destroy(context);
return 0;
}
(easywsclient库)
#include "easywsclient.hpp"
using namespace cv;
using easywsclient::WebSocket;
static WebSocket::pointer ws = NULL;
void handle_message(const std::string & message)
{
printf(">>> %s\n", message.c_str());
if (message == "world") { ws->close(); }
}
int main()
{
#ifdef _WIN32
INT rc;
WSADATA wsaData;
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (rc) {
printf("WSAStartup Failed.\n");
return 1;
}
#endif
cJSON* cjson_test = NULL;
char* str = NULL;
/* 创建一个JSON数据对象(链表头结点) */
cjson_test = cJSON_CreateObject();
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
cJSON_AddStringToObject(cjson_test, "id", "0");
/* 添加一条整数类型的JSON数据(添加一个链表节点) */
// cJSON_AddNumberToObject(cjson_test, "id", "0");
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
cJSON_AddStringToObject(cjson_test, "image", "abc");
/* 打印JSON对象(整条链表)的所有数据 */
str = cJSON_Print(cjson_test);
printf("JSON String:\n%s\n", str);
ws = WebSocket::from_url("ws://47.100.124.211:8000/ws/ObjectDetection/");
assert(ws); 判断ws对象是否为空null ,当没有连接上的时候这个对象是NULL
//ws->send("hello");
ws->send(str);
while (ws->getReadyState() != WebSocket::CLOSED) {
ws->poll();//这个函数一定要在循环里调用,发送和接收都是基于这个函数进行异步处理的
ws->dispatch(handle_message);
}
delete ws;
#ifdef _WIN32
WSACleanup();
#endif
return 0;
}
4.组播(Multicast)通信
特点:
一对多通信,数据包发送到组播组,组内所有成员都能接收。
适用于视频直播、在线会议等场景。
C 语言案例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define MULTICAST_GROUP "239.0.0.1"
#define PORT 12345
int main() {
int sockfd;
struct sockaddr_in addr;
char *message = "Hello, multicast!";
// 创建 socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(MULTICAST_GROUP);
addr.sin_port = htons(PORT);
// 发送组播数据
if (sendto(sockfd, message, strlen(message), 0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("Sendto failed");
exit(EXIT_FAILURE);
}
printf("Multicast message sent\n");
close(sockfd);
return 0;
}
5.单播(Unicast)通信
特点:
一对一通信,数据包从发送方直接传输到接收方。
适用于大多数网络通信场景。
C 语言案例:
单播通常使用 TCP 或 UDP 实现,参考前面的 TCP/UDP 示例。
总结
TCP/UDP:分别用于可靠传输和实时传输。
WebSocket:适用于全双工实时通信。
组播:一对多通信,适合大规模数据传输。
单播:一对一通信,适用于大多数场景。