套接字编程 (多进程多线程)

三次握手:

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

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

    主动大气连接请求端,发送 ACK 标志位,应答服务器连接请求。携带确认序号。


四次挥手:

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

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

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

    主动关闭连接请求端,应答 ACK 标志位     ---- 连接全部关闭

滑动窗口:


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


错误处理函数:

    
    封装目的:

        在server.c 编程过程中突出逻辑,将出错处理与逻辑分开,可以直接跳转man 手册


    【wrap.c】                        【wrap.h】


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


    命名方式:系统调用首字母大写,方便查看man手册


        如:Listen()

    联合编译:


        server.c 和wrap.c  生成  server


        client.c 和 wrap.c 生成  client

多进程并发服务器:

    1.socket();  创建 监听套接字  1fd

    2.bind()      绑定地址结构  struct sockaddr_in  addr;

    3.listen();

    4.while(1){

        cfd = accept();  接受客户端连接请求

        pid  =fork();

        if(pid==0){

            close(1fd)

            read()

            小 --》 大

            write()

        } else if (pid》0){

            close(cfd);关闭与客户端通信的套接字 cfd

            continue

        }


    }

5.子进程:

        close(1fd)

        read()

        小 --》大

        write()

    父进程:

        close(cfd);

        注册信号捕捉函数;  SIGCHLD

        在回调函数中, 完成子进程的回收

            while(waitpid());

//server

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<signal.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<arpa/inet.h>
#include<ctype.h>

#define SRV_PORT 9999
void catch_child(int signum){
  (void)signum;
  while(waitpid(0,NULL,WNOHANG)>0);
  return ;
}


int main(){


  int lfd,cfd;
  pid_t pid;
  int ret,i;
  char buf[BUFSIZ];
  char str[BUFSIZ];

  struct sockaddr_in srv_addr,clt_addr;
  socklen_t clt_addr_len;

  bzero(&srv_addr,sizeof(srv_addr));    //将地址结构清零
  srv_addr.sin_family = AF_INET;
  srv_addr.sin_port= htons(SRV_PORT);
  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);
    printf("receive from %s at PORT %d\n",
        inet_ntop(AF_INET,&clt_addr.sin_addr,str,sizeof(str)),
        ntohs(clt_addr.sin_port));
    pid = fork();
    if(pid<0){
      perror("fork error");
      exit(1);
    }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){
        perror("sigaction error");
        exit(1);
      }

      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){
        buf[i]=toupper(buf[i]);

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



====================================================================================

//client

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>

#define SERV_PORT  9999


void sys_err(const char* str){
  perror(str);
  exit(1);
}
int main(){
  int cfd;
  char buf[BUFSIZ];
  
  struct sockaddr_in serv_addr;   //服务器地址结构

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_port = htons(SERV_PORT);

  inet_pton(AF_INET,"127.0.0.1",&serv_addr.sin_addr.s_addr);


  cfd = socket(AF_INET,SOCK_STREAM,0);
  if(cfd==-1){
    sys_err("socket error");
  }
  int ret=connect(cfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
  if(ret!=0){
    sys_err("connect error");
  }
  while(1){
    ret =read(STDIN_FILENO,buf,sizeof(buf));
    write(cfd,buf,ret);
    ret=read(cfd,buf,sizeof(buf));

    write(STDOUT_FILENO,buf,ret);
    sleep(1);

  }
  close(cfd);
 

  return 0;
}


    


多线程并发服务器: server.c

        1.socket()    创建 监听套接字 1fd

        2.bind()    绑定地址结构 struct sockaddr_in addr;

        3.listen()
        
        4.while(1){


            cfd = accept(1fd);

            pthread_create(&tid,NULL,tfn,NULL);

            pthread——detach(tid)

        }


        5.子线程

            void* tfn(void* arg){

                close(1fd)

                read(cfd)

                小-->大
    
                write(cfd)

                pthread_exit((void*)10);


            }

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


#define MAXLINE 8192


#define SERV_PORT 8000

struct s_info{                     //定义一个结构体,将地址结构和 cfd 捆绑
  struct sockaddr_in cliaddr;
  int connfd;
};
void* do_work(void* arg){
  int n,i;
  struct s_info* ts= (struct s_info*)arg;
  char buf[MAXLINE];
  char str[INET_ADDRSTRLEN];
  while(1){
    n =read(ts->connfd,buf,MAXLINE);
    if(n==0){
      printf("the client %d close\n",ts->connfd);
      break;
    }
    printf("receive from %s at PORT %d\n",
        inet_ntop(AF_INET,&(*ts).cliaddr.sin_addr,str,sizeof(str)),
        ntohs((*ts).cliaddr.sin_port));
    write(STDOUT_FILENO,buf,n);
    for(i=0;i<n;++i){
      buf[i]= toupper(buf[i]);

    }
    write(ts->connfd,buf,n);
  }
  close(ts->connfd);
  return (void*)0;
}



int main(){


  struct sockaddr_in servaddr,cliaddr;
  socklen_t cliaddr_len;
  int listenfd,connfd;
  pthread_t tid;
  struct s_info ts[256];
  int i =0;
  listenfd =socket(AF_INET,SOCK_STREAM,0);
  bzero(&servaddr,sizeof(servaddr));

  servaddr.sin_family = AF_INET;
  servaddr.sin_port= htons(SERV_PORT);
  servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

  bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
  listen(listenfd,128);
  printf("accepting client connect\n");
  while(1){
    cliaddr_len =sizeof(cliaddr);
    connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddr_len);
    ts[i].cliaddr=cliaddr;
    ts[i].connfd= connfd;
    pthread_create(&tid,NULL,do_work,(void*)&ts[i]);
    pthread_detach(tid);
    i++;

  }
  return 0;
}
发布了78 篇原创文章 · 获赞 10 · 访问量 3816

猜你喜欢

转载自blog.csdn.net/weixin_44374280/article/details/104321827