IPC通信-Socket

一、什么是网络

网络是一组计算机或网络设备通过有形的线缆或无形的媒介如无线,连接起来,按照一定的规则,进行通信的集合。

二、TCP/IP模型

TCP/IP模型
1.应用层:HTTP(万维网服务),FTP(文件传输),SMTP(电子邮件),SSH(安全远程登陆),DNS(名称<-> IP地址寻找,域名系统)
2.传输层:TCP(面向字节流), UDP(面向报文)
在这里插入图片描述
3.网络层:IP协议就在这里,它负责对数据加上IP地址和其他的数据以确定传输的目标。
4.网络接口层(数据链路层):这个层次为待传送的数据加入一个以太网协议头,并进行CRC编码,为最后的数据传输做准备。

三、四元组

源和目标 IP地址(来自网络层)源和目标端口号标识
网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

四、TCP三次握手示意图

在这里插入图片描述
五、TCP流程图
在这里插入图片描述
六、常用API函数

int socket(int domain, int type, int protocol); //新建一个socket端口
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);// 绑定socket端口
int listen(int sockfd, int backlog);//建立监听
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//进入等待客户端连接模式,并阻塞当前进程/线程
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);//客户端连接到服务器ssize_t send(int sockfd, const void *buf, size_t len, int flags); //通过已建立到通信socket发送数据,类似于函数
writessize_t recv(int sockfd, void *buf, size_t len, int flags);//接收另一端通过socket发送的数据

//网络通信相关辅助函数如下
//主机字节序/网络字节序端口号 互转
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

//IP 地址转换
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);

七、示例程序
客户端:

 	int sock_fd;
    struct sockaddr_in server_addr;
    int ret;
    char send_buf[1000];
    socklen_t send_len;

    if (argc != 2)
    {
        fprintf(stderr, "Usage:%s hostname\n\a", argv[0]);
        exit(1);
    }

    /* socket */
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);//AF_INET:IPV4;SOCK_STREAM:TCP
    if (-1 == sock_fd)
    {
        fprintf(stderr, "socket error:%s\n", strerror(errno));
        exit(1);
    }

    /* set sockaddr_in parameter*/
    memset(&server_addr, 0, sizeof(struct sockaddr_in));//clear
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT_NUMBER);
    ret = inet_aton(argv[1], &server_addr.sin_addr);  //将一个字符串IP地址转换为一个32位的网络序列IP地址
    if (0 == ret)
    {
        fprintf(stderr, "server_ip error.\n");
        close(sock_fd);
        exit(1);
    }

    /* connect */
    ret = connect(sock_fd, (const struct sockaddr*)&server_addr, sizeof(struct sockaddr));
    if (-1 == ret)
    {
        fprintf(stderr, "connect error:%s\n", strerror(errno));
        close(sock_fd);
        exit(1);
    }

    while (1)
    {
        if (fgets(send_buf, 999, stdin))
        {
            /* send */
            send_len = send(sock_fd, send_buf, strlen(send_buf), 0);
            if (send_len <= 0)
            {
                fprintf(stderr, "send error:%s\n", strerror(errno));
                close(sock_fd);
                exit(1);
            }
        }
    }

    /* close */
    close(sock_fd);

服务器:

    int sock_fd, new_fd;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int ret;
    socklen_t addr_len;
    int recv_len;
    unsigned char recv_buf[1000];
    int client_num = -1;

    signal(SIGCHLD, SIG_IGN); //在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程。按系统默认将忽略此信号。如果 父进程希望被告知其子系统的这种状态,则应捕捉此信号。信号的捕捉函数中通常调用wait函数以取得进程ID和其终止状态。这个符号表示忽略该信号,执行了相应的signal()调用后,进程会忽略类型为sig的信号

    /* socket */
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);//AF_INET:IPV4;SOCK_STREAM:TCP
    if (-1 == sock_fd)
    {
        fprintf(stderr, "socket error:%s\n\a", strerror(errno));
        exit(1);
    }

    /* set server sockaddr_in */
    memset(&server_addr, 0, sizeof(struct sockaddr_in));//clear
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY:This machine all IP
    server_addr.sin_port = htons(PORT_NUMBER);

    /* bind */
    ret = bind(sock_fd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr));
    if (-1 == ret)
    {
        fprintf(stderr, "bind error:%s\n\a", strerror(errno));
        close(sock_fd);
        exit(1);
    }

    /* listen */
    ret = listen(sock_fd, BACKLOG);
    if (-1 == ret)
    {
        fprintf(stderr, "listen error:%s\n\a", strerror(errno));
        close(sock_fd);
        exit(1);
    }

    /* accept */
    while (1)
    {
        addr_len = sizeof(struct sockaddr);
        new_fd = accept(sock_fd, (struct sockaddr*)&client_addr, &addr_len);
        if (-1 == new_fd)
        {
            fprintf(stderr, "accept error:%s\n\a", strerror(errno));
            close(sock_fd);
            exit(1);
        }

        client_num++;
        fprintf(stderr, "Server get connetion form client%d: %s\n", client_num, inet_ntoa(client_addr.sin_addr));//将一个字符串IP地址转换为一个32位的网络序列IP地址
        if (!fork())
        {
            /* Child process */
            while (1)
            {
                /* recv */
                recv_len = recv(new_fd, recv_buf, 999, 0);
                if (recv_len <= 0)
                {
                    fprintf(stderr, "recv error:%s\n\a", strerror(errno));
                    close(new_fd);
                    exit(1);
                }
                else
                {
                    recv_buf[recv_len] = '\0';
                    printf("Get msg from client%d: %s\n", client_num, recv_buf);
                }
            }
            close(new_fd);
        }
    }
    /* close */
    close(sock_fd);
    exit(0);
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
IPC-Core 是一个用于在不同进程之间进行通信的 Node.js 模块。它提供了一种简单的方式来创建进程间通信IPC)管道,以便进程可以通过消息传递进行通信。 以下是 IPC-Core 的一些常见用法: 1. 创建 IPC 服务端: ```js const ipc = require('node-ipc'); ipc.config.id = 'server'; ipc.config.retry = 1500; ipc.config.silent = true; ipc.serve(() => { ipc.server.on('message', (data, socket) => { ipc.server.emit(socket, 'response', 'Server received your message'); }); }); ipc.server.start(); ``` 2. 创建 IPC 客户端: ```js const ipc = require('node-ipc'); ipc.config.id = 'client'; ipc.config.retry = 1500; ipc.config.silent = true; ipc.connectTo('server', () => { ipc.of.server.on('connect', () => { console.log('Connected to server'); ipc.of.server.emit('message', 'Hello from client'); }); ipc.of.server.on('response', (data) => { console.log(`Server says: ${data}`); }); }); ``` 3. 发送广播消息: ```js const ipc = require('node-ipc'); ipc.config.id = 'broadcast'; ipc.config.retry = 1500; ipc.config.silent = true; ipc.serve(() => { ipc.server.on('message', (data, socket) => { ipc.server.broadcast('response', 'Broadcast message received'); }); }); ipc.server.start(); ``` 4. 监听 IPC 事件: ```js const ipc = require('node-ipc'); ipc.config.id = 'event'; ipc.config.retry = 1500; ipc.config.silent = true; ipc.serve(() => { ipc.server.on('event', (data) => { console.log(`Event received: ${data}`); }); }); ipc.server.start(); ipc.server.emit('event', 'Custom event message'); ``` 以上代码只是 IPC-Core 的一些示例用法,更多用法可以参考官方文档:https://www.npmjs.com/package/node-ipc

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C君莫笑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值