socketpair

socketpair:建立一对匿名的已经连接的套接字

#include <sys/types.h> 
#include <sys/socket.h>
int socketpair(int d, int type, int protocol, int sv[2]);

1)UNIX域

2)SOCK_STREAM SOCK_DGRAM

3)对于socketpair函数,protocol参数必须提供为0。

4)参数sv[2]是接收代表两个套接口的整数数组。每一个文件描述符代表一个套接口,并且与另一个并没有区别。

5)返回值:成功时,返回零。 出错时,返回-1,并适当地设置errno。


在ProxyManager的分派连接中,调用ProxyWorker中的send函数

 // 分派连接
        for (size_t i = 0; i < _workers.size(); ++i) {
            int ret = _workers[_idx]->send(&fds[0], (int)fds.size());
            _idx = (_idx + 1) % (int)_workers.size();
			if (ret == 0) {
				break;
			}
        }

在ProxyWorker中,start函数,父进程send,子进程读

void ProxyWorker::start() {
    if (_fd != -1) {
        ::close(_fd);
        _fd = -1;
    }

    int fd[2];
    ::socketpair(AF_UNIX, SOCK_STREAM, 0, fd); // 未命名的全双工管道  可以在fd[0] 与 fd[1]间 (父子进程间)完成通讯
    if ((_pid = fork()) == 0) { // 子进程
        Comm::LogErr("worker %u running", _startId);

        ::close(fd[0]);
        _pid = getpid();
		{
			int cpu_num = sysconf(_SC_NPROCESSORS_ONLN) - 1;
			if (cpu_num > 2){
				int cpuidx = (_startId + 1 ) % cpu_num + 1;
				cpu_set_t mask;
				CPU_ZERO(&mask);
				CPU_SET(cpuidx, &mask);

				sched_setaffinity(_pid, sizeof(mask), &mask);
			}
		}

        _mgr.init(fd[1], _startId, _step);
        _mgr.run();

        Comm::LogErr("worker exit");
        _exit(0);
    } else if (_pid > 0) { // 父进程
        ::close(fd[1]);
        _fd = fd[0];
    } else {
        //Comm::LogErr
    }
}

ProxyWorker中的send函数

int ProxyWorker::send(int* fd, int n) {
    char c = '\0';
    struct iovec iov;
    iov.iov_base = &c;
    iov.iov_len = 1;

    char buf[CMSG_SPACE(sizeof(int) * n)];
    struct msghdr msg  = { 0 };
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = buf;
    msg.msg_controllen = sizeof(buf);
    msg.msg_name = NULL;
    msg.msg_namelen = 0;

    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = CMSG_LEN(sizeof(int) * n);
    memcpy(CMSG_DATA(cmsg), fd, sizeof(int) * n);

    ssize_t s = ::sendmsg(_fd, &msg, 0);
    if (s < 0) {
        Comm::LogErr("sendmsg %ld %s", s, strerror(errno));
        return -1;
    }

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值