⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 network.c

📁 类似apache2.0的多线程技术,目的在于解决网络服务器在并发客户数很大的情况下服务器进程分配(fork)而带来的效率瓶颈.
💻 C
字号:
#include <stdio.h>#include <sys/types.h>#include <sys/uio.h>#include <sys/time.h>#include <sys/poll.h>#include <unistd.h>#include <string.h>#include <netdb.h>#include <fcntl.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/un.h>#include <time.h>#include <errno.h>#include "network.h"/* * 设置文件描述符为非阻塞。 */int fd_set_noblock(int fd){    return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK);}/* * 设置文件描述符为阻塞。 */int fd_set_block(int fd){    return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK);}/* * 读n字节。返回值: *      -1      读数据错误。 *      0       文件结束。 *      其他    读取字节数。 */int readn(int fd,void *vptr,int n){    int nleft;    int nread;    char *ptr;    ptr=vptr;    nleft=n;    while(nleft > 0)     {        if((nread=read(fd,ptr,nleft)) < 0)         {            if(EINTR == errno)                nread = 0;            else                return(-1);        }         else if (0 == nread)            break;        nleft -= nread;        ptr += nread;    }    return (n-nleft);}/* * 写n字节。返回值: *      -1      写数据错误。 *      其他    写入字节数。 */int writen(int fd, const void *vptr,int n){    int nleft;    int nwritten;    const char *ptr;    ptr=vptr;    nleft=n;    while(nleft > 0)     {        if((nwritten = write(fd,ptr,nleft)) <=0)         {            if(errno == EINTR)                nwritten = 0;            else                return -1;        }        nleft -= nwritten;        ptr += nwritten;    }    return n;}int stream_listen(char *path, int backlog){    int orig_sock;    struct sockaddr_un serv_addr;    if ((orig_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {        return -1;    }    serv_addr.sun_family = PF_UNIX;    strcpy(serv_addr.sun_path, path);    unlink(path);    if (bind(orig_sock, (struct sockaddr *)&serv_addr,                 sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path)) < 0) {        return -1;    }    listen(orig_sock, backlog);    return orig_sock;}int tcp_listen(int port, int backlog, char *listenip){    int listenfd, n;    const int on = 1;    struct linger lin;    struct addrinfo hints, *res, *ressave;    char service[16];    memset(&hints, 0, sizeof(struct addrinfo));    hints.ai_flags = AI_PASSIVE;    hints.ai_family = AF_UNSPEC;    hints.ai_socktype = SOCK_STREAM;    memset(service, 0, 16);    sprintf(service, "%d", port);    if(0 != (n = getaddrinfo(listenip, service, &hints, &res))) {        return -1;    }    ressave = res;    do {        listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);        if(listenfd < 0)             continue;        setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));        lin.l_onoff = 1;        lin.l_linger = 30;        if (setsockopt(listenfd, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0) {            close(listenfd);            return -1;        };        if(0 == bind(listenfd, res->ai_addr, res->ai_addrlen))            break;        close(listenfd);    } while((res = res->ai_next) != NULL);    listen(listenfd, backlog);    freeaddrinfo(ressave);    fd_set_block(listenfd);    return listenfd;}int udp_listen(int port){    int sockfd;    struct sockaddr_in serv_addr;    sockfd = socket(PF_INET, SOCK_DGRAM, 0);    memset(&serv_addr, 0, sizeof(struct sockaddr_in));    serv_addr.sin_family = PF_INET;    serv_addr.sin_addr.s_addr = htons(INADDR_ANY);    serv_addr.sin_port = htons(port);    bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));    return sockfd;}int stream_connect(char *path){    int fd;    struct sockaddr_un serv_addr;    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)        return -1;    serv_addr.sun_family = PF_UNIX;    strcpy(serv_addr.sun_path, path);    if (connect(fd, (struct sockaddr *)&serv_addr,                sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path)) < 0)        return -1;    return fd;}int tcp_connect(const char *host, int port){    int fd;    struct hostent *h;    struct sockaddr_in sin;    if (0 == (h = gethostbyname(host)))         return -1;    memset(&sin, 0, sizeof(sin));    sin.sin_family = h->h_addrtype;    memcpy(&sin.sin_addr, h->h_addr, h->h_length);    sin.sin_port = htons(port);    if ((fd = socket(sin.sin_family, SOCK_STREAM, 0)) < 0)        return -1;    if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)))         return -1;    return fd;}int udp_connect(const char *host, int port){    int fd;    struct hostent *h;    struct sockaddr_in sin;    if (0 == (h = gethostbyname(host)))         return -1;    memset(&sin, 0, sizeof(sin));    sin.sin_family = h->h_addrtype;    memcpy(&sin.sin_addr, h->h_addr, h->h_length);    sin.sin_port = htons(port);    if ((fd = socket(sin.sin_family, SOCK_DGRAM, 0)) < 0)        return -1;    if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)))         return -1;    return fd;}int t_write(int fd, int sec, char *buf, int len){    struct pollfd pd;    pd.fd = fd;    pd.events = POLLOUT;    if (poll(&pd, 1, 1000 * sec) <= 0)	return -1;	return -1;    if (pd.revents & POLLOUT)        return write(fd,buf,len);    return -1;}int t_read(int fd, int sec, char *buf, int len){    struct pollfd pd;    pd.fd = fd;    pd.events = POLLIN;    if (poll(&pd, 1, 1000 * sec) <= 0)	return -1;    if (pd.revents & POLLIN)        return read(fd,buf,len);    return -1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -