套接字(Socket)是用于进程间通信(IPC)的一种接口技术,它可以协调不同计算机上的进程间的通信,也就是基于网络的通信。同时,它也可以用于同一台计算机上的进程间通信。
套接字通信的方式有多种。以下是一些关于使用套接字进行进程间通信的基础知识:
套接字的类型:
套接字的域:
套接字的创建:
在服务器端和客户端都需要创建套接字。这通常涉及到调用 socket()
系统调用,指定套接字的域、类型和协议。
服务器端操作:
客户端操作:
数据传输:
send()
和 recv()
函数,服务器和客户端可以互相发送和接收数据。错误处理:
在整个过程中,需要适当处理可能出现的错误,如连接失败、发送或接收数据时的错误等。
服务器:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORT 8080
int main() {
int server_sock, client_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(struct sockaddr_in);
char message[100];
// 创建套接字
if ((server_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
// 设置服务器地址信息
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// 绑定套接字到指定地址
if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("binding failed");
exit(EXIT_FAILURE);
}
// 开始监听连接请求
if (listen(server_sock, 5) == -1) {
perror("listening failed");
exit(EXIT_FAILURE);
}
printf("Server is listening on port %d...\n", PORT);
while (1) {
// 接受客户端连接请求
if ((client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &addr_len)) == -1) {
perror("accept failed");
continue;
}
printf("Accepted connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
// 接收客户端发送的消息
if (recv(client_sock, message, sizeof(message), 0) <= 0) {
perror("recv failed");
close(client_sock);
continue;
}
printf("Received message: %s\n", message);
// 发送回复消息给客户端
strcpy(message, "Hello from server!");
if (send(client_sock, message, strlen(message), 0) <= 0) {
perror("send failed");
close(client_sock);
continue;
}
printf("Sent reply to client\n");
// 关闭与客户端的连接
close(client_sock);
}
// 关闭服务器套接字
close(server_sock);
return 0;
}
客户端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SERVER_IP "127.0.0.1"
#define PORT 8080
int main() {
int client_sock;
struct sockaddr_in server_addr;
char message[100];
// 创建套接字
if ((client_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
// 设置服务器地址信息
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
perror("invalid address / address not supported");
exit(EXIT_FAILURE);
}
// 连接到服务器
if (connect(client_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connection failed");
exit(EXIT_FAILURE);
}
printf("Connected to server at %s:%d\n", SERVER_IP, PORT);
// 发送消息给服务器
strcpy(message, "Hello from client!");
if (send(client_sock, message, strlen(message), 0) <= 0) {
perror("send failed");
exit(EXIT_FAILURE);
}
printf("Sent message to server\n");
// 接收服务器的回复
if (recv(client_sock, message, sizeof(message), 0) <= 0) {
perror("recv failed");
exit(EXIT_FAILURE);
}
printf("Received reply from server: %s\n", message);
// 关闭套接字
close(client_sock);
return 0;
}
在这个例子中,服务器在本地主机的8080端口上监听连接请求。客户端连接到服务器,并发送一条消息。服务器接收消息,然后回复一条消息给客户端。最后,客户端接收回复并关闭连接。注意,你需要将SERVER_IP变量设置为你的服务器的实际IP地址(在这个例子中,我们使用的是本地回环地址127.0.0.1)。
套接字通信提供了灵活且强大的机制来进行进程间通信,无论是本地还是网络环境。然而,它也相对复杂,需要处理诸如连接管理、数据流控制、错误处理等问题,所以我们再使用的时候,一定要评估好技术方案,是否有必要通过套接字实现进程通讯。