C/S系统实现两数求和

  • 任务要求:

  1. 实现配置文件

  2. 实现日志滚动

  3. 设置非阻塞套接字,EPOLL实现

  4. 检测客户端的连接,设置心跳检测

  5. 主线程 + 心跳检测线程 + EPOLL的ET模式处理事务线程

    注意事项:设置volatile类型跳出死循环

  • 作品简介:

本次实验分为bin,config,include,log,src五个文件夹以及一个makefile文件,下面是里面的具体内容以及功能详解:

      1. bin: 存放二进制文件,生成的可执行文件,执行本系统只需在超级终端打开即可。

      2. config: 存放配置文件,客户可以在里面设置所要连接的服务器的ip以及端口,以及所要发送的数据。

      3. include: 存放本系统的头文件。

      4. log:存放日志文件,当一个文件大于10M的时候会新建一个文件存放名是log+数字,后缀名是txt。

      5. src:存放本系统的源代码,里面两个文件夹,client存放客户机的源代码,server存放服务器的源代码。

      6. makefile:本系统的编译文件,在终端打开主目录,输入命令make即可。

  • 具体实现:

  • 客户机:

      • 从ini配置文件中得到连接服务器的ip以及端口,向服务端发送数据包,以及心跳检测发送心跳包。

        • 客户端是以阻塞的方式向服务端发送数据(由于公司业务主要在服务端,所以在这里不用过多要求),主线程分出一个发送心跳线程每隔3秒向用户发送一个数据包;数据包格式:

        • 头部是一个短整型,存放数据包的格式;

          0代表发送的是心跳包,4代表发送的是不完整包,8代表发送的包完整。

        • 然后是一个长度为16的字符数组,存放客户的名字,这里用客户的ip来代替。

        • 接下来是两个整型代表发送的两个数字,也就是本任务发送的主要数据。

  • 客户端每隔3秒发送一个心跳包,由服务器检测心跳,从配置文件读取发送的数据向客户端发送数据,由服务器检测数据完整性,ip和端口存放在配置文件的IP项目下,数据在TWONUMBER项目下。

  • 接收从服务端发来的数据,用data_type判断当前数据是否完整,完整就接受输出从服务器得到的数据;

  • 服务器:

    • 服务器实现检测连接,epoll处理事物,两种工作模式(et, lt)

    • 主线程里面包含两个线程,心跳检测线程以及et/lt事物处理线程:

      • 心跳检测线程:

        检测用户是否掉线,每隔3秒计数器加1,当et接收到客户传来的数据包时,重置计数器,当计数器达到5的时候断开连接。用户用链表连接。

      • et事物处理线程:

        接受客户端发来的连接,处理客户端发来的数据包,完整性检测。

          1. 从waitepoll中得到事物后,判断是连接请求还是发送请求,如果是连接请求就接受连接,如果是发送请求就接收数据。

          2. 建立连接后要在客户链表中加入客户信息。

          3. 由于是非阻塞模式所以要循环接收数据,接收到数据包后进行心跳处理,初始化心跳计数器,写入日志文件,什么时间接收了什么数据,或者发送了什么数据。。。

      • lt事物处理线程:

        由于本次任务是et模式下,所以lt只是实现了接收数据,如果想要查看效果则需要在server.c中把et换为lt即可,lt工作模式比较简单,由于lt在接收数据时,一次没接收完,下次还会发送事物请求,所以不必要一次接收完,只需要判断连接请求建立连接,发送请求接收数据即可,不必要循环接收。

实现代码:

  • 客户端代码:
  • client.c:客户端主代码
    #include "handsomecui.h"
    #include "config.h"
    #include "heart_client.h"
    #define BUFFER_SIZE 40 int main(int argc, char *argv[])
    {
    int client_sockfd;
    int len;
    struct sockaddr_in remote_addr;
    memset(&remote_addr,,sizeof(remote_addr));
    remote_addr.sin_family=AF_INET;
    char s_ip[];
    GetConfigFileStringValue("IPANDPORT", "IP", "127.0.0.1", s_ip, sizeof(s_ip), "Config.ini");
    printf("IP : %s\n", s_ip);
    remote_addr.sin_addr.s_addr=inet_addr(s_ip); uint16_t port = GetConfigFileIntValue("IPANDPORT", "PORT", , "Config.ini");
    printf("port : %d\n", (int)port);
    if (port == -)
    {
    printf("Get port failed!\n");
    return -;
    } remote_addr.sin_port=htons(port); client_sockfd=socket(PF_INET,SOCK_STREAM,); if(client_sockfd<)
    {
    perror("client socket creation failed");
    exit(EXIT_FAILURE);
    } if(connect(client_sockfd,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr))<)
    {
    perror("connect to server failed");
    exit(EXIT_FAILURE);
    } pthread_t pth;
    int err;
    int *client_sockfd_1 = (int *)malloc(sizeof(int));
    *client_sockfd_1 = client_sockfd;
    if((err = pthread_create(&pth, NULL, send_heart, (void *)client_sockfd_1)) != ){
    fprintf(stderr, "pthread_create: %s\n", strerror(err));
    exit();
    }
    sleep(); pd = (DATA_PACK *)malloc(sizeof(DATA_PACK));
    char *buf = (char *)malloc(sizeof(*pd));
    pd->data_type = ;
    strcpy(pd->name, "127.0.0.1");
    pd->num1= (int )GetConfigFileIntValue("TWONUMBER", "NUMBER1", 0xfffffff, "Config.ini");
    pd->num2 = (int )GetConfigFileIntValue("TWONUMBER", "NUMBER2", 0xfffffff, "Config.ini");
    len = sizeof(*pd);
    memcpy(buf, pd, len);
    send(client_sockfd,buf,len,);
    free(pd); len=recv(client_sockfd,pd,BUFFER_SIZE,);
    if(pd->data_type == )
    printf("receive from server %s: %d\n",pd->name, pd->num1);
    else
    printf("receive from server %s: 发送数字个数不正确\n", pd->name);
    if(len<)
    {
    perror("receive from server failed");
    exit(EXIT_FAILURE);
    }
    close(client_sockfd);
    return ;
    }

    config.c:配置文件

    #include "config.h"
    void GetCompletePath(UINT8 *pszConfigFileName, UINT8 *pszWholePath)
    {
    UINT8 *pszHomePath = NULL;
    UINT8 szWholePath[] = {}; if (pszConfigFileName == NULL || pszWholePath == NULL)
    {
    printf("GetCompletePath: input parameter(s) is NULL!\n");
    return;
    } pszHomePath = (UINT8 *)getenv("HOME");
    if (pszHomePath == NULL)
    {
    printf("GetCompletePath: Can't find home path!\n");
    return;
    } snprintf(szWholePath, sizeof(szWholePath)-, "/home/handsome/work/socket/Cuijunyong_3/config/%s", pszConfigFileName); strncpy(pszWholePath, szWholePath, strlen(szWholePath));
    } void GetStringContentValue(FILE *fp, UINT8 *pszSectionName, UINT8 *pszKeyName, UINT8 *pszOutput, UINT32 iOutputLen)
    {
    UINT8 szSectionName[] = {};
    UINT8 szKeyName[] = {};
    UINT8 szContentLine[] = {};
    UINT8 szContentLineBak[] = {};
    UINT32 iContentLineLen = ;
    UINT32 iPositionFlag = ; if (fp == NULL || pszSectionName == NULL || pszKeyName == NULL || pszOutput == NULL)
    {
    printf("GetStringContentValue: input parameter(s) is NULL!\n");
    return;
    } sprintf(szSectionName, "[%s]", pszSectionName);
    strcpy(szKeyName, pszKeyName); while (feof(fp) == )
    {
    memset(szContentLine, 0x00, sizeof(szContentLine));
    fgets(szContentLine, sizeof(szContentLine), fp); if (szContentLine[] == ';' || szContentLine[] == '\r' || szContentLine[] == '\n' || szContentLine[] == '\0')
    {
    continue;
    } if (strncasecmp(szSectionName, szContentLine, strlen(szSectionName)) == )
    {
    while (feof(fp) == )
    {
    memset(szContentLine, 0x00, sizeof(szContentLine));
    memset(szContentLineBak, 0x00, sizeof(szContentLineBak));
    fgets(szContentLine, sizeof(szContentLine), fp); if (szContentLine[] == ';')
    {
    continue;
    } memcpy(szContentLineBak, szContentLine, strlen(szContentLine)); if (strncasecmp(szKeyName, szContentLineBak, strlen(szKeyName)) == )
    {
    iContentLineLen = strlen(szContentLine);
    for (iPositionFlag = strlen(szKeyName); iPositionFlag <= iContentLineLen; iPositionFlag ++)
    {
    if (szContentLine[iPositionFlag] == ' ')
    {
    continue;
    }
    if (szContentLine[iPositionFlag] == '=')
    {
    break;
    } iPositionFlag = iContentLineLen + ;
    break;
    } iPositionFlag = iPositionFlag + ; if (iPositionFlag > iContentLineLen)
    {
    continue;
    } memset(szContentLine, 0x00, sizeof(szContentLine));
    strcpy(szContentLine, szContentLineBak + iPositionFlag); for (iPositionFlag = ; iPositionFlag < strlen(szContentLine); iPositionFlag ++)
    {
    if (szContentLine[iPositionFlag] == '\r' || szContentLine[iPositionFlag] == '\n' || szContentLine[iPositionFlag] == '\0')
    {
    szContentLine[iPositionFlag] = '\0';
    break;
    }
    } strncpy(pszOutput, szContentLine, iOutputLen-);
    break;
    }
    else if (szContentLine[] == '[')
    {
    break;
    }
    }
    break;
    }
    }
    } void GetConfigFileStringValue(UINT8 *pszSectionName, UINT8 *pszKeyName, UINT8 *pDefaultVal, UINT8 *pszOutput, UINT32 iOutputLen, UINT8 *pszConfigFileName)
    {
    FILE *fp = NULL;
    UINT8 szWholePath[] = {}; if (pszSectionName == NULL || pszKeyName == NULL || pszOutput == NULL || pszConfigFileName == NULL)
    {
    printf("GetConfigFileStringValue: input parameter(s) is NULL!\n");
    return;
    } if (pDefaultVal == NULL)
    {
    strcpy(pszOutput, "");
    }
    else
    {
    strcpy(pszOutput, pDefaultVal);
    } GetCompletePath(pszConfigFileName, szWholePath);
    fp = fopen(szWholePath, "r");
    if (fp == NULL)
    {
    printf("GetConfigFileStringValue: open %s failed!\n", szWholePath);
    return;
    } GetStringContentValue(fp, pszSectionName, pszKeyName, pszOutput, iOutputLen); fclose(fp);
    fp = NULL;
    } INT32 GetConfigFileIntValue(UINT8 *pszSectionName, UINT8 *pszKeyName, UINT32 iDefaultVal, UINT8 *pszConfigFileName)
    {
    UINT8 szGetValue[] = {};
    INT32 iGetValue = ; if (pszSectionName == NULL || pszKeyName == NULL || pszConfigFileName == NULL)
    {
    printf("GetConfigFileIntValue: input parameter(s) is NULL!\n");
    return -;
    } GetConfigFileStringValue(pszSectionName, pszKeyName, NULL, szGetValue, -, pszConfigFileName); if (szGetValue[] == '\0' || szGetValue[] == ';')
    {
    iGetValue = iDefaultVal;
    }
    else
    {
    iGetValue = atoi(szGetValue);
    } return iGetValue;
    }

    heart_client.c:心跳发送

    #include "handsomecui.h"
    #include "heart.h" void *send_heart(void *addr)
    {
    int* client_sockfd = (int*)addr;
    printf("client_socket: %d\n", *client_sockfd);
    pd = (DATA_PACK *)malloc(sizeof(DATA_PACK));
    pd->data_type = ;
    strcpy(pd->name, "127.0.0.1");
    while(){
    // write(client_sockfd,pd,sizeof(DATA_PACK));
    send(*client_sockfd,pd,sizeof(*pd),);
    sleep(); //定时3秒
    }
    free(client_sockfd);
    free(pd);
    return NULL;
    }
  • 服务端代码
    • addfd.c:添加epoll事件

      #include "handsomecui.h"
      #include "addfd.h" void addfd(int epollfd, int fd, int flag){
      struct epoll_event event;
      memset(&event, 0x00, sizeof(event));
      event.data.fd = fd;
      event.events = EPOLLIN;
      if(flag){
      event.events |= EPOLLET;
      }
      epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
      setnonblocking(fd);
      }

      et.c:et工作模式

      #include "handsomecui.h"
      #include "et.h"
      #include "heart.h"
      extern s_t *s_head;
      #define MAX_LEN 1024
      extern volatile g_stop;
      void *et(void *arg){
      pth_etlt *pth_arg = (pth_etlt *)arg;
      struct epoll_event* events = pth_arg->events;
      int number = pth_arg->number;
      int epollfd = pth_arg->epollfd;
      int listenfd = pth_arg->listenfd;
      int i;
      DATA_PACK *data = (DATA_PACK *)malloc(sizeof(DATA_PACK));
      int p = ;
      DATA_PACK *num = (DATA_PACK *)malloc(sizeof(DATA_PACK));
      char *buf = (char *)malloc(sizeof(*num));
      int len = sizeof(*num); for(i = ; i < number; i++){
      int sockfd = events[i].data.fd;
      struct sockaddr_in client_address;
      if(sockfd == listenfd){
      socklen_t client_addresslen = sizeof(client_address);
      int connfd = accept(listenfd, (struct sockaddr*)&client_address, &client_addresslen);
      addfd(epollfd, connfd, );
      printf("client ip: %s port: %d\n", inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
      s_t *p = (s_t *)malloc(sizeof(s_t)), *q;
      strcpy(p->peerip, inet_ntoa(client_address.sin_addr));
      strcpy(p->name, inet_ntoa(client_address.sin_addr));
      p->sockfd = sockfd;
      p->count = ;
      q = s_head->next;
      s_head->next = p;
      p->next = q; }
      else if(events[i].events & EPOLLIN){
      // printf("ET once\r\n");
      while(g_stop){
      //printf("g_stop = %d\n", g_stop);
      //memset(data, 0x00, sizeof(*data));
      int ret = recv(sockfd, data, MAX_LEN, );
      if(ret < ){
      if((errno == EAGAIN) || (errno == EWOULDBLOCK)){
      //printf("read later \r\n");
      break;
      }
      close(sockfd);
      break;
      }
      else if(ret == ){
      close(sockfd);
      }
      else{
      heart_handler(sockfd, data);
      // printf("接受的数据长度是: %d\n", ret);
      // printf("recv data from %d buf id %s %d %d \r\n", sockfd, data->name, data->num1, data->num2);
      if(data->data_type == ){
      if(data->num1 == 0xfffffff || data->num2 == 0xfffffff){
      // printf("输入的数字个数不对\n");
      WriteSysLog(data, );
      num->data_type = ;
      strcpy(num->name, "127.0.0.1");
      send(sockfd, buf, len, );
      break;
      }
      WriteSysLog(data, );
      strcpy(num->name, "127.0.0.1");
      num->data_type = ;
      num->num1 = data->num1 + data->num2;
      memcpy(buf, num, len);
      WriteSysLog(num, );
      send(sockfd, buf, len, );
      }
      }
      } }
      else{
      printf("做了另外的事情\r\n");
      }
      }
      pthread_exit((void *)data);
      }

      heart.c:心跳检测,心跳处理

      #include "handsomecui.h"
      #include "heart.h" extern s_t *s_head;
      extern volatile g_stop; void init_shead(){
      s_head = (s_t *)malloc(sizeof(s_t));
      } void heart_handler(int sockfd,DATA_PACK *pd)
      {
      s_t *cur = s_head->next; while( NULL != cur){ if(strcmp(cur->name,pd->name) == ){ cur->count = ; printf("客户端IP: %s :用户 %s 连接正常\n",cur->peerip,pd->name);
      }
      cur = cur->next;
      }
      } void *heart_check(void *p)
      {
      printf("心跳检测线程已开启!\n"); while(g_stop){
      check_handler();
      sleep();
      // printf("stop = %d\n", g_stop);
      }
      // puts("******");
      pthread_exit((void *));
      } void check_handler(){ s_t *temp = NULL; s_t **ppNode = &s_head->next; while(NULL != (*ppNode) && g_stop){ if((*ppNode)->count == ){
      g_stop = ;
      printf("客户端IP: %s :用户 %s 已经掉线!!\n",(*ppNode)->peerip,(*ppNode)->name); close((*ppNode)->sockfd); temp = *ppNode; *ppNode = (*ppNode)->next; free(temp); temp = NULL; return;
      }
      else if((*ppNode)->count > ){ printf("客户端IP: %s :用户 %s 连接异常!\n",(*ppNode)->peerip,(*ppNode)->name); (*ppNode)->count++; printf("count = %d\n",(*ppNode)->count); ppNode = &((*ppNode)->next); continue;
      }
      else if((*ppNode)->count == ){ (*ppNode)->count++; printf("count = %d\n",(*ppNode)->count); ppNode = &((*ppNode)->next);
      }
      else;
      } }

      log.c:滚动日志文件

      #include "handsomecui.h"
      #include "log.h" typedef unsigned char UINT8;
      typedef signed int INT32;
      typedef unsigned int UINT32; void WriteSysLog(DATA_PACK *str, int s_w){ char buf[], temp[];
      long MAXLEN = **;
      time_t timep;
      int fp;
      struct tm *p; time(&timep);
      p = localtime(&timep);
      memset(buf,,sizeof(buf));
      sprintf(buf,"%d-%d-%d %d:%d:%d : ",(+p->tm_year),(+p->tm_mon),\
      p->tm_mday,p->tm_hour, p->tm_min, p->tm_sec); if(!s_w)
      strcat(buf, "收到了");
      sprintf(temp, "%s", str->name);
      strcat(buf, temp);
      if(s_w)
      strcat(buf, "服务器发送了数据: ");
      if(!s_w)
      strcat(buf, "传来的数据: ");
      if(s_w < ){
      sprintf(temp, "%d", str->num1);
      strcat(buf, temp);
      strcat(buf, "\t");
      sprintf(temp, "%d", str->num2);
      if(!s_w)
      strcat(buf, temp);
      strcat(buf, "\n");
      }
      else
      strcat(buf, "发送数字数目不正确\n");
      UINT8 *pszHomePath = (UINT8 *)getenv("HOME");
      UINT8 szWholePath[] = {};
      UINT8 pszConfigFileName[];
      strcpy(pszConfigFileName, "log.txt");
      if (pszHomePath == NULL)
      {
      printf("GetCompletePath: Can't find home path!\n");
      return;
      }
      snprintf(szWholePath, sizeof(szWholePath)-, "/home/handsome/work/socket/Cuijunyong_3/log/%s", pszConfigFileName);
      //puts(szWholePath);
      fp = open(szWholePath,O_RDONLY|O_CREAT|O_WRONLY, );
      if(fp < )
      {
      fprintf(stderr, "open file 1 error: %s\n", strerror(errno));
      }
      else
      {
      off_t n = lseek(fp, , SEEK_END);
      // printf("文件的字节数是:%d\n", (int)n);
      if(n >= MAXLEN)
      {
      close(fp);
      int i;
      for(i = ; i < ; i++){
      strcpy(pszConfigFileName, "log");
      temp[] = i + '';
      temp[] = '\0';
      strcat(pszConfigFileName, temp);
      strcat(pszConfigFileName, ".txt");
      snprintf(szWholePath, sizeof(szWholePath)-, "/home/handsome/work/socket/Cuijunyong_3/log/%s", pszConfigFileName);
      puts(szWholePath);
      fp = open(szWholePath,O_RDONLY|O_CREAT|O_WRONLY, );
      n = lseek(fp, , SEEK_END);
      if(n >= MAXLEN){
      close(fp);
      continue;
      }
      else{
      puts(buf);
      write(fp, buf, strlen(buf));
      close(fp);
      return;
      }
      }
      }
      else
      {
      printf("%s", buf);
      write(fp, buf, strlen(buf));
      close(fp);
      }
      }
      }

      lt.c:lt工作模式

      #include "handsomecui.h"
      #include "lt.h" void lt(struct epoll_event* events, int number, int epollfd, int listenfd){
      char buf[BUF_SIZE];
      int i;
      for(i = ; i < number; i++){
      int sockfd = events[i].data.fd;
      if(sockfd == listenfd){
      struct sockaddr_in client_address;
      socklen_t client_addresslen = sizeof(client_address);
      int connfd = accept(listenfd, (struct sockaddr *)&client_address, &client_addresslen);
      if(connfd < ){
      printf("接受失败\r\n");
      exit();
      }
      addfd(epollfd, connfd, );
      }
      else if(events[i].events & EPOLLIN){
      printf("LT once\r\n");
      memset(buf, 0x00, sizeof(buf));
      int ret = recv(sockfd, buf, sizeof(buf)-, );
      if(ret <= ){
      printf("rec 0\r\n");
      close(sockfd);
      continue;
      }
      printf("recv data from %d buf is %s\r\n", sockfd, buf);
      }
      else{
      printf("做了另外的一些事\r\n");
      }
      }
      }

      server.c:服务器主代码

      #include "handsomecui.h"
      #include "lt.h"
      #include "et.h"
      #include "addfd.h"
      #include "heart.h"
      s_t *s_head = NULL;
      volatile g_stop = ; int main(int argc, char **argv){
      if(argc <= ){
      printf("请输入ip地址和端口\r\n");
      exit();
      }
      const char* ip = argv[];
      int port = atoi(argv[]);
      int ret = ;
      struct sockaddr_in address;
      bzero(&address, sizeof(address));
      address.sin_family = AF_INET;
      inet_pton(AF_INET, ip, &address.sin_addr);
      address.sin_port = htons(port); int listenfd = socket(AF_INET, SOCK_STREAM, );
      assert(listenfd >= ); ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));
      assert(ret != -); ret = listen(listenfd, );
      assert(ret != -); struct epoll_event events[MAX_SOCKET_NUMBERS];
      int epollfd = epoll_create();
      assert(epollfd != -); addfd(epollfd,listenfd, ); int err1;
      pthread_t pth1;
      init_shead();
      if( (err1 = pthread_create(&pth1, NULL, heart_check, (void *)) ) != ){
      puts("-------------------");
      fprintf(stderr, "pthread_creat : %s\n", strerror(err1)); exit();
      }
      DATA_PACK *num;
      while(g_stop){
      int err;
      int ret = epoll_wait(epollfd, events, MAX_SOCKET_NUMBERS, -);
      if(ret < ){
      printf("epoll等候失败\r\n");
      exit();
      }
      pthread_t pth;
      pth_etlt arg = {events, ret, epollfd, listenfd};
      if( (err = pthread_create(&pth, NULL, et, (void *)&arg) ) != ){ fprintf(stderr, "pthread_creat : %s\n", strerror(err));
      exit();
      }
      //pthread_join(pth, (void**)&num);
      //printf("num1 = %d num2 = %d\n", num->num1, num->num2);
      //lt(events, ret, epollfd, listenfd);
      }
      close(listenfd);
      return ;
      }

      setnonblocking.c:设置非阻塞

      #include "handsomecui.h"
      #include "setnonblocking.h" int setnonblocking(int fd){
      int old_option = fcntl(fd, F_GETFL);
      int new_option = old_option | O_NONBLOCK;
      fcntl(fd, F_SETFL, new_option);
      return new_option;
      }

配置文件config.ini:

[IPANDPORT]
;the name of IP
IP=127.0.0.1
;the age of employee
PORT= [TWONUMBER]
;the name of employer
NUMBER1=
;the age of employer
NUMBER2=

原文地址:http://www.cnblogs.com/handsomecui/p/5694262.html

C/S系统实现两数求和(非阻塞+epoll+心跳包检测用户在线状况+滚动日志+配置文件.)的更多相关文章

  1. 面试之leetcode两数求和

    1 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样 ...

  2. 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO

    同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...

  3. 转 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO

    此文章为转载,如有侵权,请联系本人.转载出处,http://blog.chinaunix.net/uid-28458801-id-4464639.html 同步(synchronous) IO和异步( ...

  4. python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...

  5. socket编程-阻塞和非阻塞

    转自:https://www.cnblogs.com/sunziying/p/6501045.html 建立连接 阻塞方式下,connect首先发送SYN请求道服务器,当客户端收到服务器返回的SYN的 ...

  6. 阻塞IO、非阻塞IO的区别

    1.类与类之间的关系:依赖,实现,泛化(继承),关联,组合,聚合. 1)依赖(虚线):一个类是 另一个类的函数参数 或者 函数返回值. 2)实现(实线加小圆):对纯虚函数类(抽象类)的实现. 3)继承 ...

  7. IO阻塞模型 非阻塞模型

       IO阻塞模型(blocking IO) 在linux中,默认情况下所有的socket都是blocking,一个典型的读操作流程大概是这样:  所以,blocking IO的特点就是在IO执行的两 ...

  8. python开发IO模型:阻塞&非阻塞&异步IO&多路复用&selectors

    一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...

  9. 网络编程中阻塞和非阻塞socket的区别

    阻塞socket和非阻塞socket 建立连接阻塞方式下,connect首先发送SYN请求道服务器,当客户端收到服务器返回的SYN的确认时,则connect返回.否则的话一直阻塞.非阻塞方式,conn ...

随机推荐

  1. javascript正則表達式 &quot;\b&quot;问题

    preface 昨晚在看<javascript权威指南>后.看见作者自己封装一个兼容全部浏览器的山寨HTML5新API classLIst类.自己想了想认为自己也要去玩一下.可是能力还是有 ...

  2. 为iPhone6设计自适应布局(二)

    Size Classes 自适应布局的布局约束自然是好东西,但也不是万能的,有时候我们也需要使用最基本的布局,所以使用size classes将它们两者结合起来才能碰撞出更有激情的火花. 引用我上篇译 ...

  3. HDU--4784 Dinner Coming Soon DP+BFS

    题意非常长非常变态.一个人要到他男朋友家,他最初有R元以及T分钟的时间来赶到他男朋友家.有N个房子M条道路,每条道路有须要消耗的时间以及过路费,同一时候还要顺路做食盐生意,起初身上没有食盐,最多带B袋 ...

  4. pagefile.sys怎么删除

    pagefile.sys是虚拟内存文件,目地是使用一部分硬盘空间来充当内存使用.当一个程序请求的内存空间大于物理内存时,就需要pagefile.sys文件来提供较大的虚拟内存,从而满足程序对大内存的需 ...

  5. 为自己的Android应用添加广告

    平时也写了不少Android小应用,但是都是做练习之用,从来没有想过添加广告赚钱这一说. 个人是非常反感在应用内添加广告这种行为的,非常影响用户体验,不小心点到广告的话,手机流量哗哗地就没了··· 但 ...

  6. Key lock 的秘密

    研究死锁,或者观察sp_lock,有时候最恼人的莫过于你看到下面研究成果的key lock,但是却不知道究竟是哪个page 哪个row被lock住了: Exec sp_lock:   就说上面的key ...

  7. MessageDigest 类

    MessageDigest 类    MessageDigest 类是一个引擎类,它是为了提供诸如 SHA1 或 MD5 等密码上安全的报文摘要功能而设计的.密码上安全的报文摘要可接受任意大小的输入( ...

  8. Tomcat 7.0 进入项目管理页面时的密码问题

    tomcat7 这个版本,官方网下载的原始包项目管理页面的权限和之前版本的配置有点区别. 到Tomcat的conf文件夹下找到tomcat-users.xml文件,有配置权限的配置文件.     ma ...

  9. iOS_SN_详解沙河(转载)

    一 查看沙盒结构 和一些百度来的博客显示隐藏稳文件的方式不同,本文也提供两种方式,简单粗暴. 方式一 使用工具simpholders(推荐) 下载链接 http://simpholders.com/  ...

  10. angularjs字符串插值($interpolate)

    <!DOCTYPE html> <html lang="zh-CN" ng-app="app"> <head> <me ...