• l8-d8 TCP并发实现


    一、TCP多进程并发

    1.地址快速重用

    先退出服务端,后退出客户端,则服务端会出现以下错误:

    地址仍在使用中

    解决方法:

    /*地址快速重用*/
        int flag=1,len= sizeof (int);
        if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, len) == -1) {
                  perror("setsockopt");
                  exit(1);
        }

     2.多进程并发

    1)fork函数

    1. #include
    2. #include
    3. #include
    4. int main(int argc, char *argv[])
    5. {
    6.     pid_t pid = fork();
    7.     if(pid < 0){
    8.         perror("fork");
    9.         exit(0);
    10.     }else if(pid == 0){
    11.         printf("This is child process.\n");
    12.     }else{
    13.         printf("This is father process.\n");
    14.         wait(NULL);
    15.     }
    16.     return 0;
    17. }

    2)多个客户端

    代码演示

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #define BACKLOG 5
    10. void ClinetHandle(int newfd);
    11. int main(int argc, char *argv[])
    12. {
    13. int fd, newfd;
    14. struct sockaddr_in addr, clint_addr;
    15. socklen_t addrlen = sizeof(clint_addr);
    16. pid_t pid;
    17. if(argc < 3){
    18. fprintf(stderr, "%s\n", argv[0]);
    19. exit(0);
    20. }
    21. /*创建套接字*/
    22. fd = socket(AF_INET, SOCK_STREAM, 0);
    23. if(fd < 0){
    24. perror("socket");
    25. exit(0);
    26. }
    27. addr.sin_family = AF_INET;
    28. addr.sin_port = htons( atoi(argv[2]) );
    29. if ( inet_aton(argv[1], &addr.sin_addr) == 0) {
    30. fprintf(stderr, "Invalid address\n");
    31. exit(EXIT_FAILURE);
    32. }
    33. /*地址快速重用*/
    34. int flag=1,len= sizeof (int);
    35. if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, len) == -1) {
    36. perror("setsockopt");
    37. exit(1);
    38. }
    39. /*绑定通信结构体*/
    40. if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){
    41. perror("bind");
    42. exit(0);
    43. }
    44. /*设置套接字为监听模式*/
    45. if(listen(fd, BACKLOG) == -1){
    46. perror("listen");
    47. exit(0);
    48. }
    49. while(1){
    50. /*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/
    51. newfd = accept(fd, (struct sockaddr *)&clint_addr, &addrlen);
    52. if(newfd < 0){
    53. perror("accept");
    54. exit(0);
    55. }
    56. printf("addr:%s port:%d\n", inet_ntoa(clint_addr.sin_addr), ntohs(clint_addr.sin_port) );
    57. if( (pid = fork() ) < 0){
    58. perror("fork");
    59. exit(0);
    60. }else if(pid == 0){
    61. close(fd);
    62. ClinetHandle(newfd);
    63. exit(0);
    64. }
    65. else
    66. close(newfd);
    67. }
    68. close(fd);
    69. return 0;
    70. }
    71. void ClinetHandle(int newfd){
    72. int ret;
    73. char buf[BUFSIZ] = {};
    74. while(1){
    75. //memset(buf, 0, BUFSIZ);
    76. bzero(buf, BUFSIZ); //初始化
    77. ret = read(newfd, buf, BUFSIZ);
    78. if(ret < 0)
    79. {
    80. perror("read");
    81. exit(0);
    82. }
    83. else if(ret == 0)
    84. break;
    85. else
    86. printf("buf = %s\n", buf);
    87. }
    88. close(newfd);
    89. }

    二、僵尸进程处理

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #define BACKLOG 5
    12. void SigHandle(int sig){
    13. if(sig == SIGCHLD){
    14. printf("client exited\n");
    15. wait(NULL);
    16. }
    17. }
    18. void ClinetHandle(int newfd);
    19. int main(int argc, char *argv[])
    20. {
    21. int fd, newfd;
    22. struct sockaddr_in addr, clint_addr;
    23. socklen_t addrlen = sizeof(clint_addr);
    24. #if 0
    25. struct sigaction act;
    26. act.sa_handler = SigHandle;
    27. act.sa_flags = SA_RESTART;
    28. sigemptyset(&act.sa_mask);
    29. sigaction(SIGCHLD, &act, NULL);
    30. #else
    31. signal(SIGCHLD, SigHandle);
    32. #endif
    33. pid_t pid;
    34. if(argc < 3){
    35. fprintf(stderr, "%s\n", argv[0]);
    36. exit(0);
    37. }
    38. /*创建套接字*/
    39. fd = socket(AF_INET, SOCK_STREAM, 0);
    40. if(fd < 0){
    41. perror("socket");
    42. exit(0);
    43. }
    44. addr.sin_family = AF_INET;
    45. addr.sin_port = htons( atoi(argv[2]) );
    46. if ( inet_aton(argv[1], &addr.sin_addr) == 0) {
    47. fprintf(stderr, "Invalid address\n");
    48. exit(EXIT_FAILURE);
    49. }
    50. /*地址快速重用*/
    51. int flag=1,len= sizeof (int);
    52. if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, len) == -1) {
    53. perror("setsockopt");
    54. exit(1);
    55. }
    56. /*绑定通信结构体*/
    57. if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){
    58. perror("bind");
    59. exit(0);
    60. }
    61. /*设置套接字为监听模式*/
    62. if(listen(fd, BACKLOG) == -1){
    63. perror("listen");
    64. exit(0);
    65. }
    66. while(1){
    67. /*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/
    68. newfd = accept(fd, (struct sockaddr *)&clint_addr, &addrlen);
    69. if(newfd < 0){
    70. perror("accept");
    71. exit(0);
    72. }
    73. printf("addr:%s port:%d\n", inet_ntoa(clint_addr.sin_addr), ntohs(clint_addr.sin_port) );
    74. if( (pid = fork() ) < 0){
    75. perror("fork");
    76. exit(0);
    77. }else if(pid == 0){
    78. close(fd);
    79. ClinetHandle(newfd);
    80. exit(0);
    81. }
    82. else
    83. close(newfd);
    84. }
    85. close(fd);
    86. return 0;
    87. }
    88. void ClinetHandle(int newfd){
    89. int ret;
    90. char buf[BUFSIZ] = {};
    91. while(1){
    92. //memset(buf, 0, BUFSIZ);
    93. bzero(buf, BUFSIZ);
    94. ret = read(newfd, buf, BUFSIZ);
    95. if(ret < 0)
    96. {
    97. perror("read");
    98. exit(0);
    99. }
    100. else if(ret == 0)
    101. break;
    102. else
    103. printf("buf = %s\n", buf);
    104. }
    105. close(newfd);
    106. }

    三、TCP并发多线程

     

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #define BACKLOG 5
    11. void *ClinetHandle(void *arg);
    12. int main(int argc, char *argv[])
    13. {
    14. int fd, newfd;
    15. struct sockaddr_in addr, clint_addr;
    16. pthread_t tid;
    17. socklen_t addrlen = sizeof(clint_addr);
    18. if(argc < 3){
    19. fprintf(stderr, "%s\n", argv[0]);
    20. exit(0);
    21. }
    22. /*创建套接字*/
    23. fd = socket(AF_INET, SOCK_STREAM, 0);
    24. if(fd < 0){
    25. perror("socket");
    26. exit(0);
    27. }
    28. addr.sin_family = AF_INET;
    29. addr.sin_port = htons( atoi(argv[2]) );
    30. if ( inet_aton(argv[1], &addr.sin_addr) == 0) {
    31. fprintf(stderr, "Invalid address\n");
    32. exit(EXIT_FAILURE);
    33. }
    34. /*地址快速重用*/
    35. int flag=1,len= sizeof (int);
    36. if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, len) == -1) {
    37. perror("setsockopt");
    38. exit(1);
    39. }
    40. /*绑定通信结构体*/
    41. if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){
    42. perror("bind");
    43. exit(0);
    44. }
    45. /*设置套接字为监听模式*/
    46. if(listen(fd, BACKLOG) == -1){
    47. perror("listen");
    48. exit(0);
    49. }
    50. while(1){
    51. /*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/
    52. newfd = accept(fd, (struct sockaddr *)&clint_addr, &addrlen);
    53. if(newfd < 0){
    54. perror("accept");
    55. exit(0);
    56. }
    57. printf("addr:%s port:%d\n", inet_ntoa(clint_addr.sin_addr), ntohs(clint_addr.sin_port) );
    58. pthread_create(&tid, NULL, ClinetHandle, &newfd); //创建线程
    59. pthread_detach(tid); //设置为分离属性
    60. }
    61. close(fd);
    62. return 0;
    63. }
    64. void *ClinetHandle(void *arg){
    65. int ret;
    66. char buf[BUFSIZ] = {};
    67. int newfd = *(int *)arg; //传参,强转
    68. while(1){
    69. //memset(buf, 0, BUFSIZ);
    70. bzero(buf, BUFSIZ);
    71. ret = read(newfd, buf, BUFSIZ);
    72. if(ret < 0)
    73. {
    74. perror("read");
    75. exit(0);
    76. }
    77. else if(ret == 0)
    78. break;
    79. else
    80. printf("buf = %s\n", buf);
    81. }
    82. printf("client exited\n");
    83. close(newfd);
    84. return NULL;
    85. }

    Makefile


    CC=gcc
    CFLAGS=-Wall
    all:client server

    server:server.c
        $(CC) $^ -Wall -o $@ -lpthread

    clean:
        rm client server
     

  • 相关阅读:
    MMDetection在ScanNet上训练
    万字长文:一文彻底搞懂Elasticsearch中Geo数据类型查询、聚合、排序
    Navicat 15 下载、安装、重装
    妙啊,Python 管道 Pipe 编写代码如此优雅
    openssl客户端编程:一个不起眼的函数导致的SSL会话失败问题
    超标量处理器设计 姚永斌 第8章 指令发射 摘录
    net-java-php-python-单位办公OA系统计算机毕业设计程序
    第四代智能井盖传感器:万宾科技助力城市安全
    Java中 \n \f \r \t 含义
    some和every
  • 原文地址:https://blog.csdn.net/revengeman/article/details/132744417