Pipe实现本地通讯&TCP实现局域网通讯

内容摘要

本文介绍如何使用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;
}

参考链接

Linux下的C++ socket编程实例

(Windows)C++:实现socket通信(TCP/IP)实例

windows pipe

(Linux)c++ pipe 管道_c++笔记(无名管道)

(Linux)进程间的通信方式——pipe(管道)

(Windows)Why does my compiler not accept fork(), despite my inclusion of <unistd.h>?

WSL安装教程(安装Linux子系统)

上一篇:Linux杂谈(2):Select简介


下一篇:linux进程间通讯,(父子进程间)