当前位置: 首页 > news >正文

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函数

#include <stdio.h>
#include <wait.h>
#include <stdlib.h>int main(int argc, char *argv[])
{pid_t pid = fork();if(pid < 0){perror("fork");exit(0);}else if(pid == 0){printf("This is child process.\n");}else{printf("This is father process.\n");wait(NULL);}return 0;
}

2)多个客户端

代码演示

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>#define BACKLOG 5
void ClinetHandle(int newfd);
int main(int argc, char *argv[])
{int fd, newfd;struct sockaddr_in addr, clint_addr;socklen_t addrlen = sizeof(clint_addr);pid_t pid;if(argc < 3){fprintf(stderr, "%s<addr><port>\n", argv[0]);exit(0);}/*创建套接字*/fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){perror("socket");exit(0);}addr.sin_family = AF_INET;addr.sin_port = htons( atoi(argv[2]) );if ( inet_aton(argv[1], &addr.sin_addr) == 0) {fprintf(stderr, "Invalid address\n");exit(EXIT_FAILURE);}/*地址快速重用*/int flag=1,len= sizeof (int); if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, len) == -1) { perror("setsockopt"); exit(1); } /*绑定通信结构体*/if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){perror("bind");exit(0);}/*设置套接字为监听模式*/if(listen(fd, BACKLOG) == -1){perror("listen");exit(0);}while(1){/*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/newfd = accept(fd, (struct sockaddr *)&clint_addr, &addrlen);if(newfd < 0){perror("accept");exit(0);}printf("addr:%s port:%d\n", inet_ntoa(clint_addr.sin_addr), ntohs(clint_addr.sin_port) );if( (pid = fork() ) < 0){perror("fork");exit(0);}else if(pid == 0){close(fd);ClinetHandle(newfd);exit(0);}elseclose(newfd);}close(fd);return 0;
}
void ClinetHandle(int newfd){int ret;char buf[BUFSIZ] = {};while(1){//memset(buf, 0, BUFSIZ);bzero(buf, BUFSIZ);        //初始化ret = read(newfd, buf, BUFSIZ);if(ret < 0){perror("read");exit(0);}else if(ret == 0)break;elseprintf("buf = %s\n", buf);}close(newfd);
}

二、僵尸进程处理

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <sys/wait.h>#define BACKLOG 5
void SigHandle(int sig){if(sig == SIGCHLD){printf("client exited\n");wait(NULL);}
}
void ClinetHandle(int newfd);
int main(int argc, char *argv[])
{int fd, newfd;struct sockaddr_in addr, clint_addr;socklen_t addrlen = sizeof(clint_addr);#if 0struct sigaction act;act.sa_handler = SigHandle;act.sa_flags = SA_RESTART;sigemptyset(&act.sa_mask);sigaction(SIGCHLD, &act, NULL);
#elsesignal(SIGCHLD, SigHandle);
#endifpid_t pid;if(argc < 3){fprintf(stderr, "%s<addr><port>\n", argv[0]);exit(0);}/*创建套接字*/fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){perror("socket");exit(0);}addr.sin_family = AF_INET;addr.sin_port = htons( atoi(argv[2]) );if ( inet_aton(argv[1], &addr.sin_addr) == 0) {fprintf(stderr, "Invalid address\n");exit(EXIT_FAILURE);}/*地址快速重用*/int flag=1,len= sizeof (int); if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, len) == -1) { perror("setsockopt"); exit(1); } /*绑定通信结构体*/if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){perror("bind");exit(0);}/*设置套接字为监听模式*/if(listen(fd, BACKLOG) == -1){perror("listen");exit(0);}while(1){/*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/newfd = accept(fd, (struct sockaddr *)&clint_addr, &addrlen);if(newfd < 0){perror("accept");exit(0);}printf("addr:%s port:%d\n", inet_ntoa(clint_addr.sin_addr), ntohs(clint_addr.sin_port) );if( (pid = fork() ) < 0){perror("fork");exit(0);}else if(pid == 0){close(fd);ClinetHandle(newfd);exit(0);}elseclose(newfd);}close(fd);return 0;
}
void ClinetHandle(int newfd){int ret;char buf[BUFSIZ] = {};while(1){//memset(buf, 0, BUFSIZ);bzero(buf, BUFSIZ);ret = read(newfd, buf, BUFSIZ);if(ret < 0){perror("read");exit(0);}else if(ret == 0)break;elseprintf("buf = %s\n", buf);}close(newfd);
}

三、TCP并发多线程

 

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <pthread.h>#define BACKLOG 5void *ClinetHandle(void *arg);
int main(int argc, char *argv[])
{int fd, newfd;struct sockaddr_in addr, clint_addr;pthread_t tid;socklen_t addrlen = sizeof(clint_addr);if(argc < 3){fprintf(stderr, "%s<addr><port>\n", argv[0]);exit(0);}/*创建套接字*/fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){perror("socket");exit(0);}addr.sin_family = AF_INET;addr.sin_port = htons( atoi(argv[2]) );if ( inet_aton(argv[1], &addr.sin_addr) == 0) {fprintf(stderr, "Invalid address\n");exit(EXIT_FAILURE);}/*地址快速重用*/int flag=1,len= sizeof (int); if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, len) == -1) { perror("setsockopt"); exit(1); } /*绑定通信结构体*/if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){perror("bind");exit(0);}/*设置套接字为监听模式*/if(listen(fd, BACKLOG) == -1){perror("listen");exit(0);}while(1){/*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/newfd = accept(fd, (struct sockaddr *)&clint_addr, &addrlen);if(newfd < 0){perror("accept");exit(0);}printf("addr:%s port:%d\n", inet_ntoa(clint_addr.sin_addr), ntohs(clint_addr.sin_port) );pthread_create(&tid, NULL, ClinetHandle, &newfd);    //创建线程pthread_detach(tid);    //设置为分离属性}close(fd);return 0;
}
void *ClinetHandle(void *arg){int ret;char buf[BUFSIZ] = {};int newfd = *(int *)arg;    //传参,强转while(1){//memset(buf, 0, BUFSIZ);bzero(buf, BUFSIZ);ret = read(newfd, buf, BUFSIZ);if(ret < 0){perror("read");exit(0);}else if(ret == 0)break;elseprintf("buf = %s\n", buf);}printf("client exited\n");close(newfd);return NULL;
}

Makefile


CC=gcc
CFLAGS=-Wall
all:client server

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

clean:
    rm client server
 

http://www.lryc.cn/news/158714.html

相关文章:

  • 编写中间件以用于 Express 应用程序
  • 【2023年数学建模国赛】D题解题思路
  • python爬虫之正则表达式学习
  • 智慧能源方案:TSINGSEE青犀AI算法中台在能源行业的应用
  • 达梦数据库awr报告收集
  • c语言练习43:深入理解strcmp
  • NUC980webServer开发
  • 驱动开发--day2
  • 用户促活留存新方式——在APP中嵌入小游戏
  • MySQL 8.0.34(x64)安装笔记
  • 物流供应商实现供应链自动化的3种方法
  • Mysql更新时间列只改日期为指定日期不更改时间
  • 实时测试工具 Visual Studio 扩展 NCrunch 4.18 Crack
  • Neo4j 基本语法
  • docker常见面试题
  • 静态路由:配置和使用详解
  • 玩转Mysql系列 - 第15篇:详解视图
  • 0065__git fetch, git pull, git merge, git rebase
  • AJAX学习笔记4解决乱码问题
  • 【23种设计模式】享元模式【⭐】
  • 语音信号的仿真原理
  • VLDB 2023 | CDSBen: 字节跳动 veDB 数据库存储系统性能测试模型
  • crontab的配置参数和基础使用教程
  • 基于Python开发的玛丽大冒险小游戏(源码+可执行程序exe文件+程序配置说明书+程序使用说明书)
  • K8S之使用yaml格式定义pod
  • SSH命令详解
  • Windows SQLYog连接不上VMbox Ubuntu2204 的Mysql解决方法
  • Python中的日期和时间(一)datetime模块
  • qt触控板手势检测
  • 数据库 Redis