python進程間傳遞檔案描述符擴充庫

來源:互聯網
上載者:User

標籤:

由於python本身的線程基本上比較殘廢,所以為了利用機器的cpu,就不得不用上多進程。。。

在遊戲伺服器的設計中,最為常見的方式是:

掛一個前端伺服器,專門來維護與用戶端的串連,然後將用戶端的請求資料轉寄給後端伺服器。。。


上面的方式是現在最為正統的。。。


但是自己因為環境的限制,需要做到對用戶端透明,然後將後端的伺服器轉換成為多進程的。。。所以這裡就只有用一點比較彆扭的方法了,首先處理登入等一些常規的邏輯放在前端伺服器,當進入放進進行匹配戰鬥之後,將用戶端的socket串連直接交給後端伺服器,然後進行處理。。。。。

因此這裡就需要實現一個python能用的檔案描述符傳遞擴充庫。。。。


還好自己用C語言做過類似的東西。。。所以基本上把代碼拿過來,再用cython做一層封裝,也就能用了,這裡就直接貼代碼吧:

#include <sys/socket.h> #include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <sys/un.h>#include <string.h>#include <unistd.h>int serv_listen(const char *name);int send_fd(int sock, int fd, char* data);int recv_fd(int sock, char *data);  void close_fd(int fd);

上面是標頭檔的定義,接下來把c語言的代碼貼上來:

#include "sr.h"int sr_connect(const char *name){int fd, size;struct sockaddr_un un;memset(&un, 0, sizeof(un));un.sun_family = AF_UNIX;if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {printf("no1\n");return 0;}sprintf(un.sun_path, "%s%05d", "tmp", getpid());size = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);if (bind(fd, (struct sockaddr *)&un, size) < 0) {printf("no2\n");return 0;}strcpy(un.sun_path, name);size = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);if (connect(fd, (struct sockaddr *)&un, size) < 0) {printf("no3\n");return 0;}// if (listen(fd, 10) < 0) {// printf("no3");// }// char* hello = "hello fjs";// ssize_t out = send(fd, (void*)hello, strlen(hello), 0);// send_fd(lis, lis);return fd;}int send_fd(int sock, int fd, char* data)    {        printf("here1: %s\n", data);    struct iovec iov[1];        iov[0].iov_base = data;        iov[0].iov_len  = strlen(data);    printf("len: %d\n", strlen(data));    printf("here2: %s\n", iov[0].iov_base);        int cmsgsize = CMSG_LEN(sizeof(int));        struct cmsghdr* cmptr = (struct cmsghdr*)malloc(cmsgsize);        if(cmptr == NULL){            return -1;        }        cmptr->cmsg_level = SOL_SOCKET;        cmptr->cmsg_type = SCM_RIGHTS; // we are sending fd.        cmptr->cmsg_len = cmsgsize;            struct msghdr msg;        msg.msg_iov = iov;        msg.msg_iovlen = 1;        msg.msg_name = NULL;        msg.msg_namelen = 0;        msg.msg_control = cmptr;        msg.msg_controllen = cmsgsize;        *(int *)CMSG_DATA(cmptr) = fd;                int ret = sendmsg(sock, &msg, 0);        free(cmptr);        if (ret == -1){            return -1;        }        return 0;  }        int recv_fd(int sock, char* data)    {       int cmsgsize = CMSG_LEN(sizeof(int));        struct cmsghdr* cmptr = (struct cmsghdr*)malloc(cmsgsize);        if (cmptr == NULL) {          return -1;      }      char buf[33]; // the max buf in msg.     memset(buf, 0, 33);      struct iovec iov[1];      iov[0].iov_base = buf;        iov[0].iov_len = sizeof(buf);        struct msghdr msg;    msg.msg_iov = iov;        msg.msg_iovlen  = 1;        msg.msg_name = NULL;        msg.msg_namelen = 0;        msg.msg_control = cmptr;        msg.msg_controllen = cmsgsize;                int ret = recvmsg(sock, &msg, 0);             if (ret == -1) {            return -1;       }    int fd = *(int *)CMSG_DATA(cmptr);    strcpy(data, iov[0].iov_base);    free(cmptr);     return fd;    }void close_fd(int fd){    close(fd);}// int main()// {// int lis = serv_listen("/tmp/fjs.sock");// printf("ok\n");// char* hello = "hello fjs";// // ssize_t out = send(lis, (void*)hello, strlen(hello), 0);// send_fd(lis, lis);// }


最後貼上cython的封裝檔案:

cdef extern from "sr.h":extern int sr_connect(const char *name)extern int send_fd(int sock, int fd, char* data)extern int recv_fd(int sock, char* data)void close_fd(int fd)cdef extern from "stdlib.h":extern void *malloc(unsigned int num_bytes)extern void free(void *ptr)def connect_and_send():cdef char* dist = "/tmp/fjs.sock"cdef int fd = sr_connect(dist)send_fd(fd, fd, "fdsaf");def fjs_recv_fd(sock):cdef int fd = sockcdef char* data = <char*>malloc(33)fd = recv_fd(fd, data)try:out_data = datareturn (fd, out_data)finally:free(data)def fjs_send_fd(fd1, fd2, data):cdef int source = fd1cdef int des    = fd2send_fd(source, des, data)def fjs_close_fd(fd):cdef int now_fd = fdclose_fd(fd)


嗯。。就上面這些代碼。。。這裡需要基於unix域socket。。。。


最後吐槽一下。。。。python真他媽的慢。。。。

python進程間傳遞檔案描述符擴充庫

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.