Linux网络编程 day3 五一结假

基本概念

三次握手

主动发起连接请求端,发送SYN标志位,请求建立连接。携带数据包包号、数据字节数(0)、滑动窗口大小。

被动接收连接请求端,发送ACK标志位,同时携带SYN请求标志位。携带序号、确认序号、数据包包号、数据字节数(0)、滑动窗口大小。

主动发起连接请求端,发送ACK标志位,应答服务器连接请求。携带确认序号、数据包包号。

四次挥手

主动关闭连接请求端,发送FIN标志位。

被动关闭连接请求端,应答ACK标志位。            -------半关闭完成。

被动关闭连接请求端,发送FIN标志位。

主动关闭连接请求端,发送ACK标志位。            -------连接全部关闭

滑动窗口

发送给连接对端,本端缓冲区大小(实时),保证数据不会丢失。

出错处理封装函数

封装目的:在编程中突出逻辑,将错误处理与逻辑分开,且可以直接跳转man 手册

wacp.c

存放网络通信相关常用自定义函数

命名方式:系统调用函数首字符大写。

函数功能:调用系统调用函数,处理出错场景

联合gcc编译生成。

warp.h

存放网络通信相关常用自定义函数原型声明。

多进程并发服务器

客户端不变

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/wait.h>
#include<pthread.h>
#include<sys/socket.h>
#include<ctype.h>
#define SER_PORT 9003

void sys_err(char* s){
    perror(s);
    exit(1);
}

void catch_child(int signum)
{
    while((waitpid(0 , NULL , 0)) > 0);
    return;
}

int main(int argc , char *argv[])
{
    pid_t pid;
    int cfd , lfd ;
    char buf[1024];
    struct sockaddr_in serv_addr , clit_addr;
    bzero(&serv_addr , sizeof(serv_addr));
    serv_addr.sin_family = AF_INET ;
    serv_addr.sin_port = htons(SER_PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    socklen_t clit_len;

    lfd = socket(AF_INET , SOCK_STREAM , 0);
    if(lfd == -1)
        sys_err("socket error");
    int ret = bind(lfd , (struct sockaddr*)&serv_addr , sizeof(serv_addr));
    if(ret != 0)
        sys_err("bind error");
    listen(lfd , 128);
    clit_len = sizeof(clit_addr);
    while(1){
        cfd = accept(lfd , (struct sockaddr*)&serv_addr , &clit_len);
        if(cfd == -1)
            sys_err("accept error");
        pid = fork();
        if(pid < 0){
            sys_err("fork error");
        }else if(pid > 0){
            close(cfd);
            struct sigaction act;
            act.sa_handler = catch_child ;
            sigemptyset(&act.sa_mask);
            act.sa_flags = 0;
            sigaction(SIGCHLD , &act , NULL);
            continue;
        }else{
            close(lfd);
            break;
        }
    }
    if(pid == 0){
        int i , n ;
        while(1){
            n = read(cfd , buf , sizeof(buf));
            if(n == 0){
                close(cfd);
                exit(1);
            }
            for(i = 0 ; i < n  ; i++){
                buf[i] = toupper(buf[i]);
            }
            write(STDOUT_FILENO , buf ,n);
            write(cfd , buf , n);}
    }

    return 0 ;
}

多线程并发服务器

客户端不变

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<pthread.h>
#include<ctype.h>
#define MAXLINE 8192
void sys_err(char*s)
{
    perror(s);
    exit(1);
}

void err_thread(int ret , char*str){
    if(ret != 0){
        fprintf(stderr,"%s:%s\n" , str , strerror(ret));
        pthread_exit(NULL);
    }
    return ;
}

struct s_info{
    struct sockaddr_in cliaddr;
    int cfd;
};

void *do_work(void *arg)
{
    int n,i;
    struct s_info *ts = (struct s_info*)&arg;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN]; // 可用[+d查看

    while(1){
        n = read(ts->cfd , buf , MAXLINE);
        if(n == 0){
            printf("the client %d closed...\n" , ts->cfd);
            break;
        }
        printf("received from %s at PORT %d\n" , inet_ntop(AF_INET , &(*ts).cliaddr.sin_addr , str , sizeof(str)) , ntohs((*ts).cliaddr.sin_port));
        for(i = 0 ; i < n ; i++){
            buf[i] = toupper(buf[i]);
        }
        write(STDOUT_FILENO , buf , n);
        write(ts->cfd , buf , n);
    }
    close(ts->cfd);
    return (void*) 0;
}

int main(int argc , char *argv[])
{
    pthread_t tid;
    struct s_info ts[256];
    socklen_t client_len;
    int lfd , cfd;
    int ret ,i ;
    struct sockaddr_in serv_addr , clit_addr;
    bzero(&serv_addr , sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(9002);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    lfd = socket(AF_INET , SOCK_STREAM , 0);
    if(lfd == -1)
        sys_err("socket error");
    ret = bind(lfd , (struct sockaddr*)&serv_addr , sizeof(serv_addr));
    if(ret == -1)
        sys_err("bind error");
    listen(lfd , 128);
    while(1){
        client_len = sizeof(clit_addr);
        cfd = accept(lfd , (struct sockaddr*)&clit_addr , &client_len);
        if(ret != 0)
            sys_err("accept error");
        ts[i].cliaddr = clit_addr;
        ts[i].cfd = cfd;
        pthread_create(&tid , NULL , do_work , (void*)&ts[i]);
        pthread_detach(tid);  // 子线程分离 , 防止僵尸线程产生。
        i++;
    }
    return 0 ;
}

数返回值

1、>0 实际读到的字节数

2、=0 已经读到结尾(对端已经关闭) 

3、-1 进一步判断errno的值

errno = EAGAIN or EWOULDBLOCK 设置了非阻塞方式读。没有数据到达

errno = EINTE 慢速系统调用被中断

errno = "其他情况" 异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值