<3> 紫光展锐[ENGPC] Linux基础知识之Socket域套接字,进程间通信

Socket是一个很强大的东西,在Linux上有个概念就是一切皆文件.当然这个说法不严谨,比如进程就不是文件,哈哈,但是我们平常还是可以用这个概念的,就像经典力学和量子力学的关系一样,经典力学在常规条件下还是成立的,Linux中的设备目前有3大类,分别为:字符设备、块设备、网络设备,其中字符设备和块设备一般都是通过文件IO操作的,而网络设备则是通过socket套接字来操作的,可见socket的地位.socket除了可以用在网络间通信之外,还可以用在进程间通信,EngPC这里就用到了socket进程间通信,所以,我们这里就讲一下进程间通信,网络通信这一块,如果后面有机会的话,我可能会通过写一个简单的服务器的方式进行讲解.

回到主题先来看一下socket的框架:

无论是网络通信还是进程间通信,都是这个流程,区别就是填写参数的区别.关于每一步是干嘛的,上图中都有说明,我们直接通过代码进行演示进程间通信,下面是一个服务端代码:

#include <stdio.h>
#include <stdlib.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>


#define UNIX_DOMAIN "/home/george/1702/lianxi/local_socket/UNIX.domain"


int main(void)
{
    socklen_t clt_addr_len;
    int listen_fd = -1,
	clt_fd	= -1,
	ret	= -1,
	i = -1, len = 0;
    static char recv_buff[128];
    struct sockaddr_un clt_addr;
    struct sockaddr_un srv_addr;

    listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if(listen_fd < 0){
	perror("socket failed");
	exit(1);
    }

    // set srv_addr param
    srv_addr.sun_family = AF_UNIX;
    strcpy(srv_addr.sun_path, UNIX_DOMAIN);
    unlink(UNIX_DOMAIN);

    // bind socket and addr
    ret = bind(listen_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
    if(ret < 0){
	perror("bind failed");
	goto err;
    }

    // listen port, 1 client port
    ret = listen(listen_fd, 1);
    if(ret < 0){
	perror("listen failed");
	goto err;
    }

    printf("wait client...\n");

    // accept client
    len = sizeof(clt_addr);
    clt_fd = accept(listen_fd, (struct sockaddr*)&clt_addr, &len);
    if(clt_fd < 0){
	perror("accept failed");
	goto err;
    }

    printf("client connected...\n");

    memset(recv_buff, 0, 128);
    int num = read(clt_fd, recv_buff, sizeof(recv_buff));
    printf("receive num: %d, content: %s\n", num, recv_buff);

    close(clt_fd);
    close(listen_fd);
    unlink(UNIX_DOMAIN);

    return 0;

err:
    close(listen_fd);
    return -1;
}

然后是一个客户端代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>


#define UNIX_DOMAIN "/home/george/1702/lianxi/local_socket/UNIX.domain"


int main(void)
{
    int connect_fd = -1,
        ret = -1;
    char send_buf[128];
    static struct sockaddr_un srv_addr;

    // create unix socket
    connect_fd = socket(PF_UNIX, SOCK_STREAM, 0);
    if(connect_fd < 0){
	perror("socket failed");
	exit(1);
    }

    // set srv_addr param
    srv_addr.sun_family = AF_UNIX;
    strcpy(srv_addr.sun_path, UNIX_DOMAIN);

    // connect server
    ret = connect(connect_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
    if(ret < 0){
	perror("connect failed");
	close(connect_fd);
	exit(1);
    }

    // send message to server
    memset(send_buf, 0, 128);
    strcpy(send_buf, "hello girl");
    write(connect_fd, send_buf, strlen(send_buf));

    close(connect_fd);

    return 0;
}

编译之后,我们开启两个shell终端,一个运行服务端,一个运行客户端.首先我们在其中一个运行服务端,然后,服务端会阻塞并监听socket,等待客户端连接,等待有客户端连接,就等待客户端发送数据给服务端,服务端接收到数据显示,因为只是演示,所以这里没有采用循环接收和发送的方式,直接就运行一遍就结束了.服务器端收到数据并显示的效果如下:

猜你喜欢

转载自blog.csdn.net/qq_23922117/article/details/81142573
今日推荐