网络编程2——CS模型的TCP通信流程总结 及 server、client的实现

一、socket模型创建流程图

在这里插入图片描述

二、server的实现

1,报错文件先写好,基本头文件写好,C的、网络的
2,创建socket,定义文件描述符lfd,记得要返回值检查
3,创建bind函数,其中第二个参数是服务器端地址结构,要定义及初始化并在传参时要强制转换
4,创建listen函数,传入文件描述符和允许同时接入的个数
5,创建accept函数,第二个参数是传入的已连接的客户端地址结构,因此也要定义一个客户端地址结构(不用初始化,因为是传进来的),传入时同样要强制转换,man查看手册的时候会发现accept函数的第三个参数是一个socklen_t类型的客户地址结构长度,因此也要定义一个clit_addr_len,accept函数返回值也记得检查
6,accept成功之后就开始等待连接,连接成功就可以从缓冲区中读取read待处理字符串,进行操作并写回write缓冲区
7,重要的最后一步,别忘记close文件描述符

#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
#include<ctype.h>
#define SERV_PORT 9527//定义一个端口号

void sys_err(const char * str)
{
	perror(str);
	exit(1);
}

int main(int argc, char *argv[])
{
	int lfd = 0;
	int cfd = 0;//accept返回的用于创建连接的socket
	int ret;//read会返回读到的实际字节数
	char buf[BUFSIZ];//read、write需要缓冲区,从读写到缓冲区的,一般用一个系统自带宏定义缓冲区大小,4096
	
	struct sockaddr_in serv_addr;//定义服务器端的地址结构
	struct sockaddr_in clit_addr;//定义客户端的地址结构,在accept的时候要做参数(其实可以和上一行一起写,但是第一次写还是清楚点吧
	socklen_t clit_addr_len;//定义客户端传入传出参数,accept的第三个参数,socklen_t 这是个类型,man accept中的参数类型不要弄错
	//初始化地址结构
	serv_addr.sin_family = AF_INET;//跟socket的第一个参数一样,表示IPv4还是6
	serv_addr.sin_port =htons(SERV_PORT)//不能直接放宏,要讲本地字节序转换成网络字节序 
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	lfd = socket(AF_INET, SOCK_STREAM,0);
	if(lfd == -1)//函数返回值一定要检查
	{
		sys_err("socket error");
	}
	//创建成功就得到一个文件描述符,接下来就是bind,给socket绑定地址结构
	//bing(文件描述符,地质结构的指针,地址结构长度)
	bind(lfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr));//注意第二个参数 地址结构的强转
	//bind之后listen建立最大同时通信数,再accept阻塞客户端建立连接
	listen(lfd, 128);
	clit_addr_len = sizeof(clit_addr);
	cfd = accept(lfd,(struct sockaddr*)(&clit_addr),&clit_addr_len)//注意第三个参数是传入传出参数,因此首先要有个传入值,accept会返回一个新的文件描述符
	if(cfd ==-1)
	{
		sys_err("accept error");
	}
	//创建成功,服务器就开始从客户端读内容(此处为小写字母)
	while(1){
		ret = read(cfd, buf,sizeof(buf));//读到buf中,ret就是实际读到的字节数
		write(STDOUT_FILED, buf, ret);//写到屏幕上,不然看不见
		for(int i = 0; i<ret; ++i)
		{
			buf[i] = toupper(buf[i]);//注意用到一个新函数就要去看看该函数的头文件ctype.h
			write(cfd, buf, ret);
		}//这就转换完毕,再给写回到buf中
	}
	close(lfd);
	close(cfd);
	
}

写个makefile调试一下,没错就可以启动服务器./server,启动了服务器就开始阻塞等待连接,此时我们还没有写客户端,可以先用nc命令试一下 nc = net connect
nc IP地址 端口号(此处是9527)
光标闪烁即开始通信,就可以输入一串小写字母看是否会返回大写字符串
在这里插入图片描述

三、获取客户端地址结构

客户端跟服务器成功建立连接可以得到客户端建立连接的IP地址和端口号,因为accept函数的第二个参数就是客户端的地址结构,因此我们可以得到客户端信息:用IP地址转换函数得到IP地址,通过转换字节序函数得到端口号(ntohs)√
在这里插入图片描述网络字节序和本地字节序的转换,点分十进制是本地字节序
inet_ntop():输入是地址结构得到ip地址,网络转换成本地
inet_pton():输入是IP地址得到网络字节序形式,本地转换成网络

四、client的实现

1,建立客户端socket,一个cfd接收,并检查返回值
2,客户端不用bind,直接就可以connect,man手册查看connect参数列表
3,connect函数的第二个参数时服务器地址结构,因此要定义(已知的)服务端地址结构,
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);//服务器端口
inet_pton(AF_INET,"127.0.0.1",&ser_addr.sin_addr.s_addr);//用IP地址转换函数得到网络字节序的服务器ip地址

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

#define SERV_PORT 9527//服务器端口号

void sys_err(const char* str)
{
	perror(str);
	exit(1);
}
int main()
{
	int cfd;
	int ret;//connect要有一个接收值
	int counter = 10;
	char buf[BUFSIZ];//read的时候是从缓冲区中读的,默认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",&ser_addr.sin_addr.s_addr);
	
	cfd = socket(AF_INET, SOCK_STREAM,0);//
	if(cfd ==-1)
		sys_err("socket error");
	ret = connect(cfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));//注意参数类型,是否需要强制转换。成功返回0
	if(ret != 0 )
		sys_err("connect err");

//连接成功,就可以往socket写数据
	while(--counter)
	{
		write(cfd, "hello",5);
		//服务器会有返回值
		ret = read(cfd, buf,sizeof(buf));//读到buf中,ret是读到的字节数
		write(STDOUT_FILED,buf,ret);
	}
	close(cfd);
	return 0;
	
}

放到同一个目录下,起服务器,起客户端即可
在这里插入图片描述

五、TCP通信流程(假设是实现大小写转换)

server端:
1,socket() 创建socket
2,bind() 绑定服务器地址结构
3,listen() 设置监听上限
4,accept() 阻塞监听客户端连接
5,read(fd)读socket获取客户端数据
6,小写—>大写 toupper()
7,write(fd)
8,close()

client:
1,socket() 创建socket
2,connect() 与服务器建立连接
3,write() 写数据到socket
4,read() 读转换后的数据
5,显示读取的结果
6,close()

原创文章 119 获赞 27 访问量 6011

猜你喜欢

转载自blog.csdn.net/qq_37299596/article/details/105745348