C语言使用多进程实现高并发tcp服务器

多进程并发服务器的流程

  1. socket; 创建监听套接字
  2. bind; 绑定地址结构
  3. listen(); 设置监听上限
  4. accept();进行循环监听
  5. fork();接收到客户端请求创建新的进程
  6. close(); 与客户端通讯的套接字关闭

实现C语言并发服务器

#include <stdio.h>
#include <apra/inet.h>
#include <errno.h>
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>

void perr_exit(const char *s){
    perror(s);
    exit(-1);
}

int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
{
    int n;
    again:
    if((n = accept(fd,sa,salenptr))<0){
        if((errno == ECONNABORTED) || errno == EINTR)
            goto again;
        else
            perr_exit("accept error");
    }
    return n;
}

int Bind(int fd, struct sockaddr *sa, socklen_t salen)
{
    int n;
    if ((n = bind(fd, sa, salen))<0){
        perr_exit("bind error");
    }
    return n;
}

int Connect(int fd, const struct sockaddr *sa, socklen_t salen)
{
    int n;
    n = connect(fd, sa, salen);
    if (n < 0)
    {
        perr_exit("connect error");
    }
    return n;
}

int Listen(int fd, int backlog)
{
    int n;
    if ((n=listen(fd, backlog))<0)
    {
        perr_exit("listen error");
    }
    return n;
}

int Socket(int family, int type, int protocol)
{
    int n;
    if ((n=socket(family, type, protocol))<0)
    {
        perr_exit("socket error");
    }
    return n;
}

ssize_t Read(int fd, void *ptr, size_t nbytes)
{
    ssize_t n;
    again:
    if ( (n=read(fd, ptr, nbytes))==-1 )
    {
        if (errno == EINTR)
            goto again;
        else
            return -1;
    }
    return n;
}

ssize_t Write(int fd, const void *ptr, size_t nbytes)
{
    ssize_t n;
    again:
    if ((n=write(fd, ptr, nbytes)) == -1)
    {
        if (errno == EINTR)
            goto again;
        else
            return -1;
    }
    return n;
}

int Close(int fd)
{
    int n;
    n = close(fd);
    if (n==-1){
        perr_exit("close error");
    }
    return n;
}

// 读取指定大小的内容
ssize_t Readn(int fd, void *vptr, size_t n)
{
    size_t nleft;  //usigned int 剩余未读取的字节数
    ssize_t nread; //int 实际读到的字节数
    char *ptr;

    ptr = vptr;
    nleft = n;

    while (nleft > 0){
        if ((nread=read(fd, ptr, nleft))<0)
        {
            if(errno=EINTR)
                nread=0;
            else
                return -1;
        } else if (nread == 0)
            break;

        nleft -= nread;
        ptr += nread;

    }
    return n - nleft;

}

ssize_t Writen(int fd, const void *vptr, size_t n)
{
    size_t nleft;
    ssize_t nwritten;
    const char *ptr;

    ptr = vptr;
    nleft = n;
    while (nleft >0){
        if ((nwritten = write(fd, ptr, nleft))<=0){
            if (nwritten <0 && errno == EINTR)
                nwritten = 0;
            else
                return -1;
        }
        nleft -= nwritten;
        ptr += nwritten;
    }
    return n;
}

static ssize_t  my_read(int fd, char *ptr)
{
    static int read_cnt;
    static char *read_ptr;
    static char read_buf[100];

    if (read_cnt <=0 )
    {
        again:
        if((read_cnt = read(fd, read_buf, sizeof(read_buf)))<0){
            if (errno==EINTR)
                goto again;
            return -1;
        } else if (read_cnt == 0)
            return 0;
        read_ptr = read_buf;
    }
    read_cnt--;
    *ptr = *read_ptr++;

    return 1;
}

ssize_t Readline(int fd, void *vptr, size_t maxlen){
    ssize_t n, rc;
    char c, *ptr;
    ptr = vptr;

    for (n=1; n<maxlen; n++){
        if((rc =my_read(fd, &c))==1){
            *ptr++ = c;
            if (c == "\n")
                break;
        }else if (rc==0){
            *ptr = 0;
            return n-1;
        } else
            return -1;
    }
    *ptr = 0;
    return n;
}

int main(int agrv, char *agrc[])
{
  int lfd, cfd;
    pid_t pid;

    struct sockaddr_in srv_addr, clt_addr;

    socklen_t clt_addr_len;
    char buf[BUFSIZ];
    int ret,i;

    memset(&srv_addr, 0, sizeof(srv_addr));  // 将地址结构清0
//    bzero(&srv_addr, sizeof(srv_addr));
    srv_addr.sin_family = AF_INET;
    srv_addr.sin_port = htons(7000);
    srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    lfd = Socket(AF_INET, SOCK_STREAM, 0);

    Bind(lfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));

    Listen(lfd, 128);
    clt_addr_len = sizeof(clt_addr);
    while (1){

        cfd = Accept(lfd, (struct sockaddr *)&clt_addr, &clt_addr_len);
        // 创建子进程
        pid = fork();
        if (pid < 0) {
            perr_exit("fork error");

        } else if (pid==0){
            // 子进程
            close(lfd);
            break;
        } else{
            // 注册信号捕捉
            struct sigaction act;
            act.sa_handler = catch_child;
            sigemptyset(&act.sa_mask);
            act.sa_flags = 0;
            ret = sigaction(SIGCHLD, &act, NULL);
            if (ret!=0){
               perr_exit("sigaction error");
            }
            close(cfd);
            continue;
        }
    }
    if (pid == 0){
        for (;;){
        ret = read(cfd, buf, sizeof(buf));
        if(ret == 0){
            // 检测到客户端关闭了
            close(cfd);
            exit(1);
        }
        for (i=0; i<ret; i++){
            cout << buf[i] << endl;
            buf[i] = toupper(buf[i]);
        }
        request = buf;
        cout <<request << endl;

        write(cfd, buf, ret);
                write(STDOUT_FILENO, buf, ret);
        }
    }
}

原文地址:https://www.cnblogs.com/fandx/p/12154621.html

时间: 2024-11-02 13:19:24

C语言使用多进程实现高并发tcp服务器的相关文章

高性能、高并发TCP服务器(多线程调用libevent)

本文讲述的TCP服务器是模仿memcache中的TCP网络处理框架,其中是基于libevent网络库的. 主线程只处理监听客户端的连接请求,并将请求平均分配给子线程. 子线程处理与客户端的连接以及相关业务. 每个子线程有一个"连接"队列.每个"连接"有一个"反馈"队列. 先上个流程图,要上班了,以后再解释.代码以后再上··· 实现代码地址:http://download.csdn.net/detail/aillean/7521245

配置开发支持高并发TCP连接的Linux应用程序全攻略

http://blog.chinaunix.net/uid-20733992-id-3447120.html http://blog.chinaunix.net/space.php?uid=16480950&do=blog&id=103598 原文见:http://www.cppblog.com/flashboy/articles/47012.html1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到

Linux配置支持高并发TCP连接(socket最大连接数)

Linux配置支持高并发TCP连接(socket最大连接数)及优化内核参数 2011-08-09 15:20:58|  分类:LNMP&&LAMP|  标签:内核调优  文件系统调优  高并发调优  socket连接  ip_conntract  |字号大中小 订阅 1.修改用户进程可打开文件数限制在 Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个s

Linux下基于Erlang的高并发TCP连接压力实验

[题解整理]二分题 题目类型: 二分查找: 二分答案. 大致解题思路: 查找注意有序和返回值: 浮点数注意精度: 整数注意返回值,建议另外维护一个变量,用于储存可行解. 题目 分类 传送门 WA点 poj 2785 二分查找 题解 lightoj 1088 二分查找 题解 lightoj 1307 二分查找 题解 longlong poj 2456 整数二分答案 题解 poj 3104 整数二分答案 题解 poj 3258 整数二分答案 题解 poj 3273 整数二分答案 题解 lightoj

提升高并发量服务器性能解决思路

刚刚在网上淘了一个提升高并发量服务器性能解决思路,个人感觉非常不错,给大家分享出来,希望给您有所帮助. 提升高并发量服务器性能解决思路 一个小型的网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构.性能的要求都很简单.随着互联网业务的不断丰富,网站相关的技术经过这些年的发展,已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件.编程语言.数据库.WebServer.防火墙等各个领域都有

1支持高并发web服务器搭建

支持高并发web服务器搭建 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] CTCDN系统优化参数 关闭ipv6 避免放大攻击 开启恶意icmp错误消息保护 关闭路由转发 开启反向路径过滤 处理无源路由的包 关闭sysrq功能 core文件名中添加pid作为扩展名 开启SYN洪水攻击保护 修改消息队列长度 设置最大内存共享段大小bytes timewait的数量默认180000 系统同时保持TIME_WAIT的最大数量如果超过这个数字TIME_WAIT将立刻被清除并打印警

基于tomcat响应处理模型实现的高并发web服务器

在上一篇博客中,一个简单的AIOweb处理例子,可以看到AIO异步处理,依赖操作系统完成IO操作的Proactor处理模型确实很强大,可以是实现高并发,高响应服务器的不错选择,但是在tomcat中的connector的处理模型还依旧是基于NIO的处理,当然,我认为这可能会在以后的版本进行改进,但另一方面,我更认为AIO的负载控制方面的处理可能是比较难的,因为AIO api并没有提供我们对分配线程组的处理,而只是提供一个线程组,交给操作系统去解决io处理上的问题,所以,这可能会给需要复杂处理的负载

C\C++语言利用epoll实现高并发聊天室Demo

2019-11-19 00:19:02 参考大佬:https://github.com/LinHaoo/chat Makefile: all:server client server:server.cpp g++ $^ -o [email protected] client:client.cpp g++ $^ -o [email protected] clean: rm server client utility.h #ifndef CHAT_UTILITY_H #define CHAT_UTI

高并发计算服务器数量

每秒查询率QPS:对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,即每秒请求数,即最大谈吐能力. 并发数:并发数和QPS是不同的概念,一般说QPS会说多少并发用户下QPS,当QPS相同时,并发用户数越大,网站并发处理能力越好.当并发用户数过大时,会造成进程(线程)频繁切换,反正真正用于处理请求的时间变少,每秒能够处理的请求数反而变少,同时用户的请求等待时间也会变大. 找到最佳线程数能够让web系统更稳定,效率更高. 通过QPS和pv计算部署服务器台数:  单台服务器每天PV计算 公式