网络编程-2day
本帖最后由 ぉ沙皮狗的忧伤 于 2021-3-10 10:22 编辑TCP头格式
三次握手,四次挥手
S:连接性SYN=1,发起一个连接请求,调用connect()
A:应答位ACK=1,ack确定有效
F:断开位FIN=1,发送一个断开请求数据包,调用close
一、sever端代码编写
1、代码流程
①、socket建立流失套接字
②、signal改变该进程处理信号的方式
③、sockaddr_in成员初始化
④、bind绑定
⑤、listen设置为监听:被动连接
⑥、while循环,父进程等待连接,子进程处理已连接的客户端
2、添加头文件
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <signal.h>
#include <arpa/inet.h>
编写main函数,TCP并发服务器:采用多进程
3、建立流失套接字
//建立流失套接字
//参数1----地址族,AF_INET网络协议族
//参数2----套接字类型,SOCK_STREAM使用TCP
//参数3----protocol参数通常设置0
//返回值---成功socket ID,出错返回-1
serfd = socket( AF_INET, SOCK_STREAM, 0);
if(serfd < 0){
perror("socket failed!\n");
exit(1);
}
4、设备该进程的信号处理方式
//忽略SIGCHLD信号的处理,内核自动回收8kb物理资源
//子进程结束会发送一个SIGCHLD信号给内核
//参数1-----要处理的信号
//参数2-----处理的方式,SIG_IGN屏蔽该信号
signal( SIGCHLD, SIG_IGN);
5、绑定本地IP地址和指定接收数据端口,通过bind绑定套接字和端口
struct sockaddr_in self;
bzero( &self, sizeof(self));
self.sin_family = AF_INET; //选择ipv4协议
self.sin_port = htons(6666); //选择端口
self.sin_addr.s_addr = htonl(INADDR_ANY); //内核自动绑定
ret = bind( serfd, (struct sockaddr *)&self, sizeof(self));
if( ret < 0){
perror("bind failed!\n");
exit(1);
}6、设置为监听模式,被动连接
//参数1----被监听的套接字
//参数2----指定正在等待的最大队列长度
//返回值0或-1
ret = listen(serfd, 5);
if(ret < 0){
perror("listen failed!\n");
exit(1);
}
7、使用一个while循环,父进程等待连接,子进程处理客户端数据
while(1){
printf("wait client!\n");
//5、父进程等待连接
newfd = accept( serfd, (struct sockaddr *)&cli, &len);
if(newfd < 0){
perror("accept failed!\n");
exit(1);
}
printf("new client ip = %s port = %d ok\n", inet_ntoa(cli.sin_addr),\
ntohs(cli.sin_port));
//6、创建一个子进程
pid_t pid = fork();
if(pid < 0){
perror("fork failed!\n");
exit(1);
}
if(pid > 0)
continue;
//子进程执行代码块
if(pid == 0){
//处理已连接客户端数据
char buf;
int ret = -1;
while(1){
bzero( buf, 128);
ret = read( newfd, buf, 127);
if(ret < 0){
perror("read");
exit(1);
}
//如果客户端输入quit或者Cttl+C关闭,服务器也会关闭
if(!strncmp( buf, "quit", 4) || (buf == 0)){
close(newfd);
break;
}
printf("ip = %s port = %d buf = %s\n", inet_ntoa(cli.sin_addr),\
ntohs(cli.sin_port), buf);
}
exit(1); //结束当前进程
}
}
二、client端代码编写1、添加头文件
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>2,创建流失套接字
//创建流失套接字
//参数1----地址族,AF_INET网络协议族
//参数2----套接字类型,SOCK_STREAM使用tcp
//参数3----protocol通常设置为0
//返回值---成功socket id 失败 -1
clifd = socket( AF_INET, SOCK_STREAM, 0);
if(clifd < 0){
perror("socket failed!\n");
exit(1);
}3、主动连接服务器:指定服务器IP和接收端口
//主动连接服务器:指定服务器IP和接收端口
struct sockaddr_in ser;
bzero( &ser, sizeof(ser));
ser.sin_family = AF_INET; //AF_INET网络协议族
ser.sin_port = htons(6666); //要连接的服务器端口
ser.sin_addr.s_addr = inet_addr("172.18.12.163"); //服务器ip
ret = connect( clifd, (struct sockaddr *)&ser, sizeof(ser));
if(ret < 0){
perror("connect failed!\n");
exit(1);
}4、发送数据,从标准输入获取键盘的值
while(1){
fprintf( stderr, "input:");
bzero( buf, 128);
//从标准输入获取字符串
fgets( buf, 127, stdin);
//写入套接字中
ret = write( clifd, buf, strlen(buf));
if(ret < 0){
perror("write failed!\n");
exit(1);
}
if(!strncmp( buf, "quit", 4)){
break;
}
}三、使用gcc编译sever端代码,在虚拟机上运行,使用交叉编译工具编译client端代码,在板卡上运行
四、运行可执行程序
代码在附件中。。。。
页:
[1]