网站域名怎么快速备案,自己购买模板建站,asp 课程教学网站开发,厦门+外贸公司做网站作业#xff1a; 1. 多线程中的newfd#xff0c;能否修改成全局#xff0c;不行#xff0c;为什么#xff1f; 2. 多线程中分支线程的newfd能否不另存#xff0c;直接用指针间接访问主线程中的newfd,不行#xff0c;为什么#xff1f; 多线程并发服务器模型原代码…作业 1. 多线程中的newfd能否修改成全局不行为什么 2. 多线程中分支线程的newfd能否不另存直接用指针间接访问主线程中的newfd,不行为什么 多线程并发服务器模型原代码
#includestdio.h
#includehead.h
#includenetinet/in.h
#define PROT 1112
#define IP 192.168.125.133
void handler(int sig)
{while(waitpid(-1,NULL,WNOHANG)0);
}
struct climsg
{int nfd;struct sockaddr_in cin;};
void* deal_cli_msg(void *arg);
int main(int argc, const char *argv[])
{//捕获17信号if(signal(17,handler)SIG_ERR){ ERR_MSG(signal);return -1; } //创建流式套接字int sfdsocket(AF_INET,SOCK_STREAM,0);if(sfd0){ ERR_MSG(socket);return -1; } printf(sfd%d\n,sfd);//设置允许端口被快速复用int reuse1;if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,reuse,sizeof(reuse))0){ ERR_MSG(setsockopt);return -1; } printf(允许端口快速复用成功\n);//绑定服务器的IP和端口---必须绑定struct sockaddr_in sin;sin.sin_family AF_INET;//必须填AF_INETsin.sin_port htons(PROT);//端口号1024~49151sin.sin_addr.s_addr inet_addr(IP);//本机IPif(bind(sfd,(struct sockaddr*)sin,sizeof(sin))0){ ERR_MSG(bind);return -1; } printf(绑定成功\n);//将套接字设置为被动监听状态if(listen(sfd,128)0){ ERR_MSG(listen);return -1; } printf(被动监听状态设置成功\n);//从已完成连接的队列中获取一个客户端信息生成一个新的文件描述符struct sockaddr_in cin;//存储客户端地址信息socklen_t addrlen sizeof(cin);pthread_t tid;int nfd-1;struct climsg info;while(1){ nfdaccept(sfd,(struct sockaddr*)cin,addrlen);if(nfd0){ERR_MSG(accept);return -1; }printf([%s:%d]nfd%d,客户端连接成功\n,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),nfd);info.nfdnfd;info.cincin;//该文件描述符才是客户端通信的文件描述符if(pthread_create(tid,NULL,deal_cli_msg,(void *)info)!0){printf(pthread_create failed __%d__\n,__LINE__);return -1; }} close(sfd);return 0;
}
void* deal_cli_msg(void *arg)
{char buf[128];ssize_t res0;int nfd ((struct climsg*) arg)-nfd;struct sockaddr_in cin ((struct climsg*) arg)-cin;while(1){ bzero(buf,sizeof(buf));//接受数据resrecv(nfd,buf,sizeof(buf),0);if(res0){ERR_MSG(recv);break;}else if(0res){printf([%s:%d]nfd%d 客户端下线\n,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),nfd);break;}printf(nfd%d : %s\n,nfd,buf);//发送数据strcat(buf,*_*);if(send(nfd,buf,sizeof(buf),0)0){ERR_MSG(send);break;}printf(发送成功\n);}close(nfd);return 0;
} 1.将newfd改成全局变量效果 答不行因为newfd是全局变量的话客户端连接后生成的新的文件描述符会一直覆盖上一次保存的文件描述符导致客户端下线时只能关闭最新创建的文件描述符无法关闭之前客户端连接时创建的文件描述符。
2.不保存分支线程的newfd直接用指针间接访问主线程中的newfd效果 与第一题效果相同不保存nfd时有客户端创建连接会一直覆盖结构体里的文件描述符nfd的数据导致断开连接时关闭的文件描述符nfd取的是结构体里最新的 导致之前创建连接时开启的文件描述符没有被保存导致无法关闭。
3.基于UDP的TFTP文件传输
TFTP通信过程总结
服务器在69号端口等待客户端的请求服务器若批准此请求则使用 临时端口 与客户端进行通信。每个数据包的编号都有变化从1开始每个数据包都要得到ACK的确认如果出现超时则需要重新发送最后的数据包或ACK包数据长度以512Byte传输的小于512Byte的数据意味着数据传输结束。 下载代码
#includestdio.h
#includehead.h
#define PORT 69
int main(int argc, const char *argv[])
{char IP[128];printf(请输入IP:\n);scanf(%s,IP);char name[128];printf(请输入文件名:\n);scanf(%s,name);//创建报式套接字int sfdsocket(AF_INET,SOCK_DGRAM,0);if(sfd0){ ERR_MSG(socket);return -1; } printf(sfd%d\n,sfd);//填充客户端自身的地址信息结构体真实的地址信息结构体根据地址族指定//AF_INET : man 7 ip; struct sockaddr_in sin;sin.sin_family AF_INET;//必须填AF_INETsin.sin_port htons(PORT);//服务器端口号:1024~49151sin.sin_addr.s_addr inet_addr(IP);//服务器IP ifconfig查看ssize_t res0;struct sockaddr_in rcvaddr;socklen_t addrlen sizeof(rcvaddr);char data[516];//数据包char ACK[4];//ACK包size_t i4;char *pdata;short *p1(short*)data;*p1htons(1);char *p2data2;strcpy(p2,name);char *p3p2strlen(p2)1;strcpy(p3,octet);//发送读写请求if(sendto(sfd,p,(istrlen(p2)strlen(p3)),0,(struct sockaddr*)sin,sizeof(sin))0){ ERR_MSG(sendto);return -1; } bzero(data,sizeof(data));int fpopen(name,O_WRONLY|O_CREAT|O_TRUNC,0664);while(1){ //接收数据resrecvfrom(sfd,data,sizeof(data),0,(struct sockaddr*)rcvaddr,addrlen);if(res0){ ERR_MSG(recvfrom);return -1; } if(write(fp,data4,res-4)0){ ERR_MSG(write);close(fp);return -1; } if(res516){ printf(传输完毕\n);break;}//发送数据short *m1(short *)ACK;*m1htons(4);short *m2m11;*m2*((short *)data1);if(sendto(sfd,ACK,i,0,(struct sockaddr*)rcvaddr,sizeof(rcvaddr))0){ERR_MSG(sendto);return -1; }bzero(data,sizeof(data));bzero(ACK,sizeof(ACK));} //关闭文件描述符close(sfd);close(fp);return 0;
} 上传代码