首页 > 编程语言 >day09(网络编程基础)服务器模型

day09(网络编程基础)服务器模型

时间:2024-09-12 22:24:57浏览次数:9  
标签:printf day09 addr 编程 acceptfd saddr sockfd 服务器 include

目录

服务器模型

循环服务器

并发服务器

多进程

多线程

​​​​​​​IO多路复用

​​​​​​​并发服务器总结


服务器模型

在网络通信中,通常一个服务器要连接多个客户端

为了处理多个客户端的请求,通常有多种表现形式

循环服务器

一个服务器在同一时间只能处理一个客户端的请求

并发服务器

一个服务器在同一时间可以处理多个客户端的请求

多进程

每有一个客户端连接创建一个进程进行通信

为什么要创建进程?------》通信

什么时间创建进程?------》accept之后fork

子进程:通信

父进程:循环等待下一个客户端连接

进程资源回收----》子进程退出-----》客户端退出

wait(); waitpid();

SIGCHLD:当子进程退出给父进程发送的信号

#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>

void handler(int sig)
{
    wait(NULL);
}

int main(int argc, char const *argv[])
{
    pid_t pid;
    char buf[128] = {0};
    int ret, acceptfd;
    // 1.创建套接字(socket)---------------》有手机
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    printf("sockfd:%d\n", sockfd); // 3
    // 2.指定网络信息---------------------------》有号码
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;            // IPV4
    saddr.sin_port = htons(atoi(argv[1])); // 端口号
    // saddr.sin_addr.s_addr = inet_addr("192.168.50.13"); // 虚拟机IP
    // saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
    saddr.sin_addr.s_addr = INADDR_ANY;
    int len = sizeof(caddr);
    // 3.绑定套接字(bind)------------------》绑定手机(插卡)
    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind ok\n");
    // 4.监听套接字(listen)-----------------》待机
    if (listen(sockfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listen ok\n");
    // 5.接收客户端连接连接请求(accept)--》接电话
    // tcp服务器一共有两类文件描述符,一类用于连接,一类用于通信
    // socket函数返回值:用于连接的文件描述符
    // accept函数返回值:用于通信的文件描述符
    signal(SIGCHLD, handler);//设置信号处理方式  在哪设置皆可(作用:当接收到子进程退出的信号时,自动调用handler函数回收子进程)
    while (1)
    {
        acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
        if (acceptfd < 0)
        {
            perror("accept err");
            return -1;
        }
        printf("port:%d ip:%s\n", ntohs(caddr.sin_port), inet_ntoa(caddr.sin_addr));
        printf("acceptfd:%d\n", acceptfd);
        pid = fork();
        if (pid < 0)
        {
            perror("fork err");
            return -1;
        }
        else if (pid == 0)
        {
            // 6.接收、发送数据(recv send)---》通话
            while (1)
            {
                // read/write()
                ret = recv(acceptfd, buf, sizeof(buf), 0);
                if (ret < 0)
                {
                    perror("recv err");
                    break;
                }
                else if (ret == 0)
                {
                    printf("client exit\n");
                    break;
                }
                else
                {
                    printf("buf:%s\n", buf);
                    memset(buf, 0, sizeof(buf));
                }
            }
            // 7.关闭套接字(close)-----------------》挂电话
            close(acceptfd);
            exit(0);
        }
        else
            close(acceptfd);
    }

    close(sockfd);

    return 0;
}

多线程

每有一个客户端连接创建一个线程进行通信

为什么要创建线程-------》通信

什么时间创建线程-------》accept之后pthread_create

子线程:通信

主线程:循环等待下一个客户端连接

通信的文件描述符------》线程传参

#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>

void *handler(void *arg)
{
    int ret, acceptfd;
    acceptfd = *((int *)arg);       //强转
    char buf[128] = {0};
    // 6.接收、发送数据(recv send)---》通话
    while (1)
    {
        // read/write()
        ret = recv(acceptfd, buf, sizeof(buf), 0);
        if (ret < 0)
        {
            perror("recv err");
            return NULL;
        }
        else if (ret == 0)
        {
            printf("client exit\n");
            break;
        }
        else
        {
            printf("buf:%s\n", buf);
            memset(buf, 0, sizeof(buf));
        }
        // 7.关闭套接字(close)-----------------》挂电话
        }
    close(acceptfd);
    pthread_exit(NULL);
}

int main(int argc, char const *argv[])
{

    int acceptfd;
    pthread_t tid;
    // 1.创建套接字(socket)---------------》有手机
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    printf("sockfd:%d\n", sockfd); // 3
    // 2.指定网络信息---------------------------》有号码
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;            // IPV4
    saddr.sin_port = htons(atoi(argv[1])); // 端口号
    // saddr.sin_addr.s_addr = inet_addr("192.168.50.13"); // 虚拟机IP
    // saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
    saddr.sin_addr.s_addr = INADDR_ANY;
    int len = sizeof(caddr);
    // 3.绑定套接字(bind)------------------》绑定手机(插卡)
    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind ok\n");
    // 4.监听套接字(listen)-----------------》待机
    if (listen(sockfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listen ok\n");
    // 5.接收客户端连接连接请求(accept)--》接电话
    // tcp服务器一共有两类文件描述符,一类用于连接,一类用于通信
    // socket函数返回值:用于连接的文件描述符
    // accept函数返回值:用于通信的文件描述符
    while (1)
    {

        acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
        if (acceptfd < 0)
        {
            perror("accept err");
            return -1;
        }
        printf("port:%d ip:%s\n", ntohs(caddr.sin_port), inet_ntoa(caddr.sin_addr));
        printf("acceptfd:%d\n", acceptfd);

        pthread_create(&tid, NULL, handler, &acceptfd);
        pthread_detach(tid);
    }
    close(sockfd);

    return 0;
}

​​​​​​​IO多路复用

select  poll    epoll

​​​​​​​并发服务器总结

多进程:

优点:服务器更稳定,父子进程资源独立,安全性高

缺点:需要开辟多个进程,大量消耗资源,系统开销大

多线程:

优点:相对于多进程,资源开销小,多个线程共享同一个进程的资源

缺点:需要开辟多个线程,安全性较差

IO多路复用:

优点:节省资源、系统开销小,性能高

缺点:代码复杂度高

标签:printf,day09,addr,编程,acceptfd,saddr,sockfd,服务器,include
From: https://blog.csdn.net/QR70892/article/details/142187045

相关文章

  • ##嵌入式学习之Linux系统编程##--标准I/O函数
    day01主要内容:linux系统下一切皆文件标准IO---标准库文件IO---系统调用制作库---静态库、动态库基本概念:标准I/O:文件:一组相关数据的有序集合。文件名:这个数据集合的名称。文件类型:lsp-bcd系统调用用户空间进程访问内核的接口把用户从底层的硬件编程......
  • Python3 学习笔记6-os 模块、错误和异常、面向对象编程、类的专有方法、命名空间和作
    目录一、os模块: 常用方法: 二、错误和异常:(1)语法错误:(2)异常:(3)异常处理:(4)抛出异常:(5)用户自定义异常:(6)清理行为:(7)with语句:三、面向对象编程: (1)类和对象:(2)继承:(3)封装:(4)多态:(5)运算符重载: 四、类的专有方法:(1)__init__(self,...):(2)__del__(self):(3)__repr__(self):(4)__set......
  • 1765asp.net古镇旅游网站VS开发sqlserver数据库web结构c#编程web网页设计
    博主介绍:专注于Java.net phpphython 小程序等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作☆☆☆精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟我的博客空间发布了1000+毕设题目方便大家学习使用感兴趣的可以先收藏起来,还有大家在......
  • C语言简单编程题(思路+源码)
    C语言简单编程题(思路+源码)【一】题目一:1.字符串的逆序(如abcdef–>fedcba)思路:首先我们用strlen()函数来获得字符串的长度,用left来表示下标为零的元素,用right来表示最后一个字符的下标,创建第三个变量,交换第一个和最后一个的元素,再left++,right–,后面的依次类推。2.代码实......
  • 高防服务器优势
    想要服务器租用和服务器托管安全,一些中小企业会选择够抵御CC,DDOS等外来攻击的服务器,而这些服务器称为高防服务器。那么具体的什么是高防服务器,我们又如何辨别呢?一、什么是高防服务器?高防服务器是指独立单个硬防防御50G以上的服务器,主要是针对DDos、CC流量攻击而出现的。由于......
  • 新迁移服务器可能会出现哪些问题
    在迁移服务器过程中,可能会遇到多种问题。以下是一些常见的问题及其可能的原因:1.配置问题环境不一致:新服务器的操作系统版本、软件配置或环境变量与旧服务器不同,可能导致应用程序运行不正常。网络配置错误:IP地址、子网掩码、网关或DNS设置错误,导致网络连接问题。服务配置丢失:在迁移......
  • centos下,搭建多仓库的svn服务器
    1、安装软件yum-yinstallsubversion2、查看安装版本 svnserve--version3、创建SVN版本库目录 mkdir-p/data/svn/svnrepos4、创建版本库svnadmincreate/dadta/svnroot/tingyiqusvnadmincreate/dadta/svnroot/bbssvnadmincreate/dadta/svnroot/blog5、将其中一个仓库下......
  • 公司服务器有必要选好的系统盘吗
    公司服务器选择系统盘(通常是指固态硬盘SSD或机械硬盘HDD作为操作系统和应用程序的安装盘)时,选择一个性能良好、可靠度高的系统盘是非常有必要的。以下是选择好的系统盘的几个理由:1.启动和加载速度使用高质量的系统盘可以显著提高服务器的启动速度和应用程序的加载速度。SSD比HDD拥......
  • Express和Node中使用Fetch POST数据到服务器时遇到405错误
    和Node中使用FetchPOST数据到服务器时遇到405错误一、问题描述(一)错误现象在Express和Node中使用Fetch发送POST请求时,服务器返回了405错误。具体表现为,客户端向服务器发送POST请求后,服务器没有正确处理请求,而是返回了405错误代码,表示方法不被允许。这种错误通......
  • 程序员副业推荐专题—如果利用AI来翻译原版英文编程书籍
    一、准备工作获取原版英文编程书籍:可以从电子书商店(如AmazonKindleStore)购买电子书版本,或者从图书馆、书店等获取实体书。如果书籍有电子版,特别是EPUB、MOBI等格式,将更方便后续处理。选择AI翻译工具:市场上有多种AI翻译工具可供选择,如DeepL、GoogleTranslate......