socket网络通信

    技术2022-07-13  74

    一、发送接收

    read()/write() recv()/send() readv()/writev() recvmsg()/sendmsg() recvfrom()/sendto()

    推荐使用recvmsg()/sendmsg()函数,这两个函数是最通用的I/O函数,实际上可以把上面的其它函数都替换成这两个函数。它们的声明如下:

    #include <unistd.h> ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); #include <sys/types.h> #include <sys/socket.h> ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t recv(int sockfd, void *buf, size_t len, int flags); ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

    二、阻止SIGPIPE

    1、 进程中:

    struct sigaction sa; sa.sa_handler=handle_pipe; sigemptyset(&sa.sa_mask); sa.sa_flags=0; sigaction(SIGPIPE,&sa,0);/用于忽略sigpipe信号 struct sigaction sa; sa.sa_handler = SIG_IGN; sa.sa_flags = 0; if((sigemptyset(&sa.sa_mask) == -1) || sigaction(SIG_PIPE, &sa, 0) == -1) { perror("SIGPIPE"); exit(EXIT_FAILURE) }

    这种方法对于进程可以忽略SIGPIPE。 但是POSIX的线程,对信号的捕获是逐条线程进行的,所以引出了下面的解决方案。

    2、 多线程中: 代码应写在main函数的开头,创建线程之前。

    sigset_t signal_mask; sigemptyset(&signal_mask); sigaddset(&signal_mask, SIG_PIPE); if(pthread_sigmask(SIG_BLOCK, &signal_mask, NULL) == -1) perror("SIG_PIPE");

    这样就能屏蔽掉线程中的SIG_PIPE。

    sigset_t signal_mask; sigemptyset (&signal_mask); sigaddset (&signal_mask, SIGPIPE); int rc = pthread_sigmask (SIG_BLOCK, &signal_mask, NULL); if (rc != 0) { printf("block sigpipe error\n"); }

    3、send参数指定MSG_NOSIGNAL

    int ret=send(client_fds[i], send_message, BUFF_SIZE, MSG_NOSIGNAL); if(ret<=0)send失败则关闭该socket { printf("-------This is socket send failure! (ret<=0)--------- \n"); close(client_fds[i]); FD_CLR(client_fds[i], &ser_fdset); client_fds[i] = 0; }
    Processed: 0.016, SQL: 9