TCP是一种可靠的面向连接的协议,它提供了可靠的数据传输和错误修复机制。这使得TCP广泛用于需要可靠数据传输的应用,例如电子邮件、文件传输和Web浏览器。
当使用TCP建立连接时,它会在客户端和服务器之间创建一个虚拟的连接,并确保数据在这个连接上按照正确的顺序传输。这是通过使用序列号、确认号和窗口大小等机制来实现的。
下面是一个使用TCP的简单示例,展示了如何在服务器和客户端之间建立连接并进行通信:
服务器端(server.c):
#include
#include
#include
#include
#include
#include
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sockfd, client_sockfd;
struct sockaddr_in server_addr, client_addr;
char buffer[BUFFER_SIZE];
// 创建套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
return 1;
}
// 设置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
// 绑定套接字到服务器地址
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
return 1;
}
// 监听请求
listen(sockfd, 5);
printf("Server started. Waiting for connections...\n");
while (1) {
// 接受连接
int client_addr_len = sizeof(client_addr);
client_sockfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_addr_len);
if (client_sockfd == -1) {
perror("accept");
return 1;
}
// 读取客户端发送的消息
memset(buffer, 0, BUFFER_SIZE);
read(client_sockfd, buffer, BUFFER_SIZE);
printf("Received message from client: %s\n", buffer);
// 发送响应给客户端
write(client_sockfd, "Message received!", strlen("Message received!"));
// 关闭客户端套接字
close(client_sockfd);
}
// 关闭服务器套接字
close(sockfd);
return 0;
}
客户端(client.c):
#include
#include
#include
#include
#include
#include
#include
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sockfd;
struct sockaddr_in server_addr;
char buffer[BUFFER_SIZE];
// 创建套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
return 1;
}
// 设置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
// 连接服务器
if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror("connect");
return 1;
}
// 发送消息给服务器
printf("Enter message to send to server: ");
fgets(buffer, BUFFER_SIZE, stdin);
write(sockfd, buffer, strlen(buffer));
// 读取服务器的响应
memset(buffer, 0, BUFFER_SIZE);
read(sockfd, buffer, BUFFER_SIZE);
printf("Server response: %s\n", buffer);
// 关闭套接字
close(sockfd);
return 0;
}
以上是一个使用TCP的简单示例。在服务器端,我们首先创建一个套接字,绑定地址和端口,并开始监听客户端连接。当有客户端请求连接时,我们接受连接,读取客户端发送的消息并给出响应。在客户端,我们创建一个套接字,连接到服务器,并发送消息给服务器并读取响应。
UDP是一种无连接的协议,它提供了一种简单的数据传输机制,适用于一些不需要可靠数据传输的应用,例如游戏、流媒体和实时通信。
与TCP不同,UDP没有建立连接的过程,而是直接发送和接收数据包。UDP也不提供错误修复机制,数据包可能会丢失或乱序到达。因此,在使用UDP时,我们需要自己处理数据的可靠性和顺序问题。
以下是一个使用UDP的简单示例,展示了如何在客户端和服务器之间进行通信:
服务器端(server.c):
#include
#include
#include
#include
#include
#include
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sockfd;
struct sockaddr_in server_addr, client_addr;
char buffer[BUFFER_SIZE];
// 创建套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
perror("socket");
return 1;
}
// 设置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
// 绑定套接字到服务器地址
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
return 1;
}
printf("Server started. Waiting for messages...\n");
while (1) {
// 接收消息
memset(buffer, 0, BUFFER_SIZE);
socklen_t client_addr_len = sizeof(client_addr);
ssize_t bytes_received = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &client_addr_len);
if (bytes_received == -1) {
perror("recvfrom");
return 1;
}
printf("Received message from client: %s\n", buffer);
// 回复消息给客户端
char *response = "Message received!";
ssize_t bytes_sent = sendto(sockfd, response, strlen(response), 0, (struct sockaddr*)&client_addr, client_addr_len);
if (bytes_sent == -1) {
perror("sendto");
return 1;
}
}
// 关闭套接字
close(sockfd);
return 0;
}
客户端(client.c):
#include
#include
#include
#include
#include
#include
#include
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sockfd;
struct sockaddr_in server_addr;
char buffer[BUFFER_SIZE];
// 创建套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
perror("socket");
return 1;
}
// 设置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
// 发送消息给服务器
printf("Enter message to send to server: ");
fgets(buffer, BUFFER_SIZE, stdin);
ssize_t bytes_sent = sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (bytes_sent == -1) {
perror("sendto");
return 1;
}
// 接收服务器的响应
memset(buffer, 0, BUFFER_SIZE);
socklen_t server_addr_len = sizeof(server_addr);
ssize_t bytes_received = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&server_addr, &server_addr_len);
if (bytes_received == -1) {
perror("recvfrom");
return 1;
}
printf("Server response: %s\n", buffer);
// 关闭套接字
close(sockfd);
return 0;
}
在UDP示例中,服务器端和客户端的代码都有所变化。服务器端使用了recvfrom()
和sendto()
函数来接收和发送数据包,而不是读取和写入文件描述符。客户端同样使用了recvfrom()
和sendto()
函数来接收和发送数据包。