首页 > 系统相关 >Linux 网络基础 2 三次握手 三次挥手 多进程 多线程服务器

Linux 网络基础 2 三次握手 三次挥手 多进程 多线程服务器

时间:2023-07-21 23:11:30浏览次数:47  
标签:info 多线程 addr int Linux 三次 include buf port

1.包裹函数

对服务器客户端等函数进行报错处理 以及简化处理

比如bind

int tcp4bind(short port,const char *IP)
{
    struct sockaddr_in serv_addr;
    int lfd = Socket(AF_INET,SOCK_STREAM,0);
    bzero(&serv_addr,sizeof(serv_addr));
    if(IP == NULL){
        //如果这样使用 0.0.0.0,任意ip将可以连接
        serv_addr.sin_addr.s_addr = INADDR_ANY;
    }else{
        if(inet_pton(AF_INET,IP,&serv_addr.sin_addr.s_addr) <= 0){
            perror(IP);//转换失败
            exit(1);
        }
    }
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port   = htons(port);
   // int opt = 1;
	//setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    Bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
    return lfd;
}


2.粘包

缓冲区内 由于没发送完毕另外一个包就来了直接挤占前一个包的缓冲区(被信号打断的情况

粘包

解决方式
1.约定 一次发送固定字节数
2.数据结尾要\n
3.头部加上数据的大小

3.三次握手规则

三次握手规则

SYN 包体中的1

4.四次挥手

四次挥手

FIN

四次握手序号

四次握手序号

5.滑动窗口

mms

mms

mss 出现三次握手前两次 告知对方发送数据最大长度
MTU 跟网卡有关系 一帧最大传输单元

6.TCP流量控制

TCP报文窗口尺寸 发送报文者的最大缓冲区

流量控制

三次握手第2次告诉
发送流程

数据读取流程

7.多进程(多线程)实现并发服务器

多进程服务器

创建套接字

绑定

监听

while(1)

{

提取连接

fork创建子进程

子进程中,关闭lfd,服务客户端

​ 父进程关闭cfd,回收子进程的资源

}

关闭

并发是指两个或多个事件在同一时间间隔内发生

代码

#include<unistd.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<signal.h>
#include"wrap.h"
void free_process(int sig)
{
	pid_t pid;
	while (1)
	{
		pid = waitpid(-1, NULL, WNOHANG);
		if (pid <= 0)
		{
			break;
		}
		else
		{
			printf("进程号%d 退出\n", pid);
		}
	}

}
int main()
{
	//TCP bind ipv44
	sigset_t set;
	sigemptyset(&set);
	sigaddset(&set, SIGCHLD);
	sigprocmask(SIG_BLOCK, &set, NULL);

	int lfd = tcp4bind(8000, NULL);
	Listen(lfd, 128);
	struct sockaddr_in as;
	socklen_t  len = sizeof(as);
	while (1)
	{

		char ip[16] = "";
		int cfd = Accept(lfd, (struct sockaddr*)&as, &len);
		printf("新的主机 ip=%s port=%d \n", inet_ntop(AF_INET, &as.sin_addr.s_addr, ip, 16), ntohs(as.sin_port));
		pid_t pid;
		pid = fork();
		if (pid < 0)
		{
			perror("fork");
			exit(0);
		}
		else if (pid == 0)
		{
			while (1)
			{
				//字进程内部
				close(lfd);
				char buf[1024] = "";
				int n = read(cfd, buf, sizeof(buf));
				if (n < 0)
				{
					perror("");
					close(cfd);
					exit(0);
				}
				else if (0 == n)
				{
					printf("主机 ip=%s port=%d  即将断开链接 \n", inet_ntop(AF_INET, &as.sin_addr.s_addr, ip, 16), ntohs(as.sin_port));
					close(cfd);
					exit(0);
				}
				else
				{
					printf("%s\n", buf);
					write(cfd, buf, n);
				}
			}

		}
		else
		{
			//父进程
			close(cfd);
			//拦截子进程退出信号 进程资源回收
			struct sigaction act;
			act.sa_flags = 0;
			act.sa_handler = free_process;
			//清空阻塞集
			sigemptyset(&act.sa_mask);
			//注册
			sigaction(SIGCHLD, &act, NULL);
			//解除阻塞
			sigprocmask(SIG_UNBLOCK, &set, NULL);
		}

		
	}
	return 0;
}
多线程实现并发服务器
#include<unistd.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<signal.h>
#include"wrap.h"
#include <pthread.h>

typedef struct agv1
{
	struct sockaddr_in cliaddr;
	int cdf;

}agv1;

void* fun(void *arg)
{
	agv1* info = (agv1*)arg;
	//打印信息
	char ip[16] = "";
	printf("客户端 ip=%s port=%d  链接 \n", inet_ntop(AF_INET, &(info->cliaddr.sin_addr.s_addr), ip, 16),
		ntohs(info->cliaddr.sin_port));
	while (1)
	{
		char buf[1024] = "";
		int count = 0;
		count = read(info->cdf, buf, sizeof(buf));
		if (count == 0)
		{
			printf("客户端 ip=%s port=%d  链接即将断开 线程即将销毁 \n", inet_ntop(AF_INET, &(info->cliaddr.sin_addr.s_addr), ip, 16),
				ntohs(info->cliaddr.sin_port));
				break;
				break;
		}
		else
		{
			printf("客户端%d : %s\n",ntohs(info->cliaddr.sin_port) ,buf);
		}

	}
	close(info->cdf);
	free(info);
	//线程设置分离 自动回收

}

int main()
{

	printf("请输入服务器端口号\n");
char buf[8] = "";
	
	read(STDIN_FILENO, buf, sizeof(buf));
	printf("   \n");
printf("等待客户端链接\n");
int port = atoi((char*)buf);
int G=9;
	if(G==9)
{
	//创建 绑定
	int lfd=tcp4bind(port, NULL);
	//监听
	Listen(lfd, 128);
	//提取
	struct sockaddr_in as;
	socklen_t  len = sizeof(as);
	agv1* info;
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	while (1)
	{
		
		pthread_t pthid;
		int cfd = Accept(lfd, (struct sockaddr*) & as, &len);
		//创建线程 ->传递参数
		info = malloc(sizeof(agv1));
		info->cdf = cfd;
		info->cliaddr = as;
		//创建线程

		pthread_create(&pthid, &attr, fun, info);

	}

}
}

标签:info,多线程,addr,int,Linux,三次,include,buf,port
From: https://www.cnblogs.com/lzfyz/p/17572569.html

相关文章

  • Linux ps -o 查看进程启动时间
    时间参数如下表参数 含义start显示进程启动时间的简短格式。通常,它会显示日期时间中的月-日或者时-分-秒start_time 显示进程启动时间的简短格式,通常格式是年或者 月-日或者 时-分,没有秒etime显示进程启动的累积时间,通常格式是天-时-分-秒......
  • linux cpp g++ mysqlconnector
    1.installmysqlinubuntu;2installmysqlconnector;sudoaptinstalllibmysqlclient-dev3.completecode#include<algorithm>#include<chrono>#include<cstdio>#include<cstdint>#include<cstdlib>#include<ctime>......
  • Archlinux+Windows 双系统安装教程(UEFI)2023七月
    前言之前的随笔本人提到过等有时间后写一篇关于manjaro与windows双系统安装的教程,但由于“这样那样的原因”,本人已不再使用manjaro,本人已经切换到archlinux的环境下,故本次的教程将主角换成了archlinux。你需要具备的一些素质1.能够自主地阅读官方文档.,按照本人的教程不代表你......
  • linux Vim配置Golang语言环境
    下载vim要配置Linux上的Vim,可以按照以下步骤进行操作:打开终端并运行以下命令安装Vim:sudoapt-getupdatesudoapt-getinstallvim12在主目录下创建.vimrc文件:cd~touch.vimrc12编辑.vimrc文件并添加您想要的配置选项。例如,您可以添加以下行以启用语法高亮和......
  • Linux下编译安装python3.7 附带python-dev
    1、安装开发工具包sudoyum-ygroupinstall"Developmenttools" 2、安装依赖包sudoyum-yinstallzlib-develbzip2-developenssl-develncurses-develsqlite-develreadline-develtk-develgdbm-develdb4-devellibpcap-develxz-devellibffi-devel ......
  • Linux系统命令提示符更改颜色
    Linux命令终端自定义修改PS11.了解PS1PS1是Linux终端用户的一个环境变量,用来定义命令行提示符的参数。在终端输入命令:$set|grepPS1可得到当前PS1的定义值:PS1='[\u@\h\W]\$'PS1的常用参数以及含义:\d:代表日期,格式为weekdaymonthdate,例如:"MonAug1"\H:完整的主机......
  • linux系统编程学习笔记
    IO当系统调用io与标准io都能完成相同功能时,优先使用标准io因为不同操作系统提供的系统调用不同,但标准io是之上的封装,不会随着系统的不同改变另外标准io可以合并系统调用,加速如标准io如fopen,在linux下依赖open,在windows下依赖openfile标准IO与系统IO区别一个吞吐量大(即先缓存......
  • linux删除文件、文件夹
    linux删除文件夹  1、除文件夹实例:rm-rf/var/log/httpd/access 将会删除/var/log/httpd/access目录以及其下所有文件、文件夹 2、删除文件使用实例:rm-f/var/log/httpd/access.log 将会强制删除/var/log/httpd/access.log这个文件......
  • Linux中内核线程可以被抢占吗?
    1背景 说起抢占,需要关注服务器上Linux内核中的CONFIG_PREEMPT_xxx采用的何种模式,下面是几个比较常见系统的配置方式例如REHL以及centos7使用的是CONFIG_PREEMPT_VOLUNTARY又例如SLES以及龙蜥OS使用的是CONFIG_PREEMPT_NONE 咱们这里要分析的就是在CONFIG_PREEMPT_VOLUN......
  • 多线程下,C++如何调用Python脚本的方法
    视频教程:多线程场景下,用C++调用Python脚本的方法Git:https://github.com/JasonLiThirty/C-andPython接口函数Python3.6提供给C/C++接口函数,基本都是定义pylifecycle.h,pythonrun.h,ceval.h中。Py_Initialize()和Py_Finalize()C++应用程序调用Python脚本之前,必须先调用Py_I......