问:有没有一种方法能够不仅跨进程,还能跨主机通信呢?
答:有,那就是全能的套接字,不过今天还是只说一下跨进程。
手册
socket(7) socket(2) bind(2) listen(2) connect(2) send(2) recv(2)
简介
套接字的功能相对于其他进程通信方法,在功能方面就是最强大的了,灵活性也很高。它可以支持全双工通信,没有同步问题。用套接字不仅可以实现跨进程通信,还可以实现面向连接(TCP)和面向无连接(UDP)这两种主流网络通信方式。
套接字常用于网络,对于进程通信,同样可以将双方或多方的其中一个理解为服务端,其它理解为客户端。
代码演示
由于功能全面,灵活性较高,所以演示代码也相对其它进程通信方式复杂一些。
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
int main(int argc, char **argv){
int fd;
char socket_file[] = "socket_file";//套接字文件
struct sockaddr_un addr;
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
memcpy(addr.sun_path, socket_file, sizeof(socket_file));
unlink(socket_file);
pid_t pid = fork();
if (pid > 0){//父进程做服务端
//创建套接字文件描述符
if ((fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0){
printf("error@%d, %s\n", __LINE__, strerror(errno));
goto PARENT_ERROR;
}
//把文件描述符绑定到套接字文件上
if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un))){
printf("error@%d, %s\n", __LINE__, strerror(errno));
goto PARENT_ERROR;
}
//监听服务请求,同时最大监听数是1
if (listen(fd, 1)){
printf("error@%d, %s\n", __LINE__, strerror(errno));
goto PARENT_ERROR;
}
{
struct sockaddr_un client_un;
unsigned int len = sizeof(struct sockaddr_un);
//接收服务请求
int client_fd = accept(fd, (struct sockaddr *)&client_un, &len);
close(fd);
if (client_fd < 0){
printf("error@%d, %s\n", __LINE__, strerror(errno));
goto PARENT_ERROR;
}
{
char test_string[] = "Can I help you?";
char rvbuf[256];
ssize_t size;
printf("[%d] send something to [%d]\n", getpid(), pid);
size = send(client_fd, test_string, sizeof(test_string), 0);
if (size != sizeof(test_string)){
printf("error@%d, %s\n", __LINE__, strerror(errno));
goto PARENT_ERROR;
}
size = recv(client_fd, rvbuf, sizeof(rvbuf), 0);
if (size <= 0){
printf("error@%d, %s\n", __LINE__, strerror(errno));
goto PARENT_ERROR;
}
printf("[%d] receive [%s] from [%d]\n", getpid(), rvbuf, pid);
}
}
PARENT_ERROR:
waitpid(pid,NULL,0);
}
else if (pid == 0){//子进程做客户端
if ((fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0){
printf("error@%d, %s\n", __LINE__, strerror(errno));
exit(EXIT_FAILURE);
}
//连接到服务端
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un))){
printf("error@%d, %s\n", __LINE__, strerror(errno));
exit(EXIT_FAILURE);
}
{
struct sockaddr_un client_un;
unsigned int len = sizeof(struct sockaddr_un);
{
char test_string[] = "I just want to say hello world.";
char rvbuf[256];
ssize_t size;
size = recv(fd, rvbuf, sizeof(rvbuf), 0);
if (size <= 0){
printf("error@%d, %s\n", __LINE__, strerror(errno));
exit(EXIT_FAILURE);
}
printf("[%d] receive [%s]\n", getpid(), rvbuf);
printf("[%d] send something back\n", getpid());
size = send(fd, test_string, sizeof(test_string), 0);
if (size != sizeof(test_string)){
printf("error@%d, %s\n", __LINE__, strerror(errno));
exit(EXIT_FAILURE);
}
}
}
exit(EXIT_SUCCESS);
}
return 0;
}
输出
[24044] send something to [24045]
[24045] receive [Can I help you?]
[24045] send something back
[24044] receive [I just want to say hello world.] from [24045]
套接字是啥意思呢?
能改成网络通信么?能写个简单的服务器/客户端么?