内容摘要
本文介绍如何使用C/C++实现Pipe进程间通讯和Socket TCP局域网通讯。
同时给出Linux下的参考代码,Windows下的参考博客。
Pipe本地通讯
需要用到的函数和库
库:unistd.h
函数:int pipe(int fd[2])
,创建匿名管道。fork()
,复制当前进程。
用法
int fd[2]; // record FILE* of pipe.
int state = pipe(fd); // create pipe.
if(state < 0){ // success 0, fail -1
printf("Create Pipe Error\n");
return -1;
}
pipe
传入一个长度为2的int数组, 返回0/-1, 表示成功/失败.
如果创建成功, 则fd[0]
为读取端, 可以使用read
读取. fd[1]
为写入端, 可以用write
写入.
pid_t pid = fork();
// This will create a child Process which has the
// same state as the father process now.
if(pid < 0){ // pid=-1, Error.
printf("Fork Error!\n");
return -1;
}else if(pid == 0){ // pid=0, this is child Process.
// Do something
}else{ // pid>0, pid is the process id of child Process
// Do something
}
fork
函数可以在linux下复制当前进程的状态, 可以简单理解为在当前节点分叉运行.
fork
函数如果返回-1
, 则表示进程创建失败. 如果返回是0
则表示当前为子进程, 返回非-1/0
则记录了子进程的pid
.
子进程会和父进程有相同的变量名和赋值(因为所有状态均Fork.
read(fd[0], message, sizeof(message)); // 从管道读取信息, 阻塞式
write(fd[1], message, strlen(message)+1); // 向管道写入信息, 阻塞式
代码
#include<unistd.h>
#include<bits/stdc++.h>
using namespace std;
int main(){
int fd[2]; // record FILE* of pipe.
int state = pipe(fd); // create pipe.
if(state < 0){ // success 0, fail -1
printf("Create Pipe Error\n");
return -1;
}
printf("Create Pipe success\n");
// fd[0]: read, fd[1]: write
printf("read: %d, write %d\n", fd[0], fd[1]);
// Create child process by fork()
pid_t pid = fork();
// This will create a child Process which has the
// same state as the father process now.
if(pid < 0){ // pid=-1, Error.
printf("Fork Error!\n");
return -1;
}else if(pid == 0){ // pid=0, this is child Process.
printf("Child Process id:%d\n", getpid());
close(fd[1]); // Close write.
char message[100];
ssize_t read_len = read(fd[0], message, sizeof(message));
if(read_len == 0){
printf("Read NULL Message!\n");
}
printf("Child read:%s\n", message);
}else{
printf("Father Process id:%d\n", getpid());
printf("Forked child id:%d\n", pid);
close(fd[0]); // Close read.
// Create message "Commit By Pipe."
char *message = "Commit By Pipe.";
write(fd[1], message, strlen(message)+1);
printf("Father send:%s\n", message);
}
return 0;
}
// Windows 没有Fork函数, 可以用CreateProcess造一个.
Socket局域网通讯
直接对着代码讲吧
// Server
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/shm.h>
#include<bits/stdc++.h>
#define PORT 5555
int main(){
// 创建套接字
int TCP_fd = socket(AF_INET, SOCK_STREAM, 0);
// 初始化套接字的端口/IP等
struct sockaddr_in server_sockaddr;
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
// 绑定配置信息
if(bind(ss, (struct sockaddr*)&server_sockaddr, sizeof(server_sockaddr))==-1){
printf("Bind Error!\n");
return -1;
}
// 设置监听
if(listen(ss, 20) == -1){
printf("Listen Queue Error!\n");
return -1;
}
// 准备链接
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
int conn = accept(ss, (struct sockaddr*)&client_addr, &length);
if(conn < 0){
printf("Connect Error\n");
return -1;
}
// 连接成功后读取信息
char buffer[1024];
while(1){
memset(buffer, 0 ,sizeof(buffer));
// 读取信息
int len = recv(conn, buffer, sizeof(buffer), 0);
if(strcmp(buffer, "exit\n") == 0){
break;
}
printf("%s", buffer);
// 向Client发送信息
send(conn, buffer, len, 0);
}
close(conn);
close(ss);
return 0;
}
// Client
#include<bits/stdc++.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/shm.h>
#define PORT 5555
#define BUFFER_SIZE 1024
int main(){
// 创建套接字 和 配置
int sock_cli = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
// 尝试链接
if (connect(sock_cli, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
printf("Connect Error!\n");
return -1;
}
// 从本地读取信息, 发送到Socket中
char sendbuf[BUFFER_SIZE], recvbuf[BUFFER_SIZE];
while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL){
send(sock_cli, sendbuf, strlen(sendbuf), 0);
if(strcmp(sendbuf,"exit\n")==0)
break;
recv(sock_cli, recvbuf, sizeof(recvbuf),0);
printf("The message that server recived is %s\n", recvbuf);
memset(sendbuf, 0, sizeof(sendbuf));
memset(recvbuf, 0, sizeof(recvbuf));
}
close(sock_cli);
return 0;
}
参考链接
(Windows)C++:实现socket通信(TCP/IP)实例
(Linux)c++ pipe 管道_c++笔记(无名管道)
(Windows)Why does my compiler not accept fork(), despite my inclusion of <unistd.h>?