网络编程day4

目录

使用多进程实现并发服务器

使用多线程实现并发服务器

流式域套接字服务器

流式域套接字客户端

报式域套接字服务器

报式域套接字客户端

tftp客户端

思维导图


使用多进程实现并发服务器

#include <myhead.h>
void sighandler(int signum){if(signum==SIGCHLD){//回收退出的僵尸进程while(waitpid(-1,NULL,WNOHANG)>0);}
}
int main(int argc, const char *argv[])
{//signal函数捕获SIGCHLD信号if(signal(SIGCHLD,sighandler)==SIG_ERR){perror("signal");return -1;}//创建套接字int sfd=socket(AF_INET,SOCK_STREAM,0);if(sfd<0){perror("socket");return -1;}//绑定//填充地址信息结构体struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(6666);sin.sin_addr.s_addr=inet_addr("192.168.125.13");if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){perror("bind");return -1;}//listenlisten(sfd,128);//接收客户端地址信息struct sockaddr_in cin;socklen_t addrlen=sizeof(cin);while(1){//acceptint newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);if(newfd<0){perror("accept");return -1;}//终端打印客户端连接信息printf("[%s %d]accept success\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));//创建子进程用于和客户端收发信息pid_t pid=fork();if(pid>0){//父进程用不到newfd,关闭父进程newfdclose(newfd);}//子进程和客户端收发信息else if(pid==0){//子进程用不到sfd,关闭sfdclose(sfd);char buf[128];while(1){memset(buf,0,sizeof(buf));if(0==recv(newfd,buf,sizeof(buf),0)){printf("[%s %d]客户端下线\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));break;}printf("[%s %d]%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),buf);strcat(buf,"*-*");send(newfd,buf,sizeof(buf),0);}close(newfd);exit(EXIT_SUCCESS);}else if(pid<0){perror("fork");close(sfd);close(newfd);}}close(sfd);return 0;
}

 使用多线程实现并发服务器

#include <myhead.h>
//多线程实现TCP并发服务器
//线程传参结构体
typedef struct{int newfd;struct sockaddr_in cin;
}para_t;void *task(void *arg);
int main(int argc, const char *argv[])
{//创建套接字int sfd=socket(AF_INET,SOCK_STREAM,0);if(sfd<0){perror("socket");return -1;}//设置端口快速重用int reuse=1;if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0){perror("setsockopt");return -1;}//填充地址信息结构体struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(6666);sin.sin_addr.s_addr=inet_addr("192.168.125.13");//绑定if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){perror("bind");return -1;}//listenlisten(sfd,128);//客户端地址信息结构体struct sockaddr_in cin;socklen_t addrlen=sizeof(cin);while(1){//接收客户端的连接int newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);if(newfd<0){perror("accept");return -1;}printf("[%s %d]accept success\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));//创建用于和客户端通信的线程para_t info={newfd,cin};pthread_t tid;if(pthread_create(&tid,NULL,task,&info)!=0){printf("pthread_create err\n");return -1;}//分离线程pthread_detach(tid);}close(sfd);return 0;
}
void *task(void *arg){int newfd=((para_t*)arg)->newfd;struct sockaddr_in cin=((para_t*)arg)->cin;char buf[128]="";while(1){//接收客户端信息memset(buf,0,sizeof(buf));if(0==recv(newfd,buf,sizeof(buf),0)){printf("[%s %d]客户端下线\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));break;}printf("[%s %d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),buf);strcpy(buf,"*-*");send(newfd,buf,sizeof(buf),0);}//关闭用于和客户端通信的套接字,退出线程close(newfd);pthread_exit(NULL);
}

 流式域套接字服务器

#include <myhead.h>
//流式域套接字服务器
int main(int argc, const char *argv[])
{//创建套接字int sfd=socket(AF_UNIX,SOCK_STREAM,0);if(sfd<0){perror("socket");return -1;}//判断套接字文件是否存在if(access("./unix",F_OK)==0){if(unlink("./unix")<0){perror("unlink");return -1;}}//填充地址信息结构体struct sockaddr_un sun;sun.sun_family=AF_UNIX;strcpy(sun.sun_path,"./unix");//绑定if(bind(sfd,(struct sockaddr*)&sun,sizeof(sun))<0){perror("bind");return -1;}//监听listen(sfd,128);//客户端地址信息结构体struct sockaddr_un cun;socklen_t addrlen=sizeof(cun);//接受客户端连接int newfd=accept(sfd,(struct sockaddr*)&cun,&addrlen);if(newfd<0){printf("accept");return -1;}printf("11\n");printf("[%s] accept success\n",cun.sun_path);char buf[128]="";while(1){memset(buf,0,sizeof(buf));if(0==recv(newfd,buf,sizeof(buf),0)){printf("[%s]客户端下线\n",cun.sun_path);break;}printf("[%s]:%s\n",cun.sun_path,buf);strcat(buf,"*-*");send(newfd,buf,sizeof(buf),0);}close(newfd);close(sfd);return 0;
}

 流式域套接字客户端

#include <myhead.h>
//流式域套接字客户端
int main(int argc, const char *argv[])
{//创建套接字int sfd=socket(AF_UNIX,SOCK_STREAM,0);if(sfd<0){perror("socket");return -1;}//tcp绑定非必须/*//判断套接字文件是否存在if(access("./unix",F_OK)==0){if(unlink("./unix")<0){perror("unlink");return -1;}}//填充地址信息结构体struct sockaddr_un sun;sun.sun_family=AF_UNIX;strcpy(sun.sun_path,"./unix");//绑定if(bind(sfd,(struct sockaddr*)&sun,sizeof(sun))<0){perror("bind");return -1;}
*/	//填充地址信息结构体struct sockaddr_un sun;sun.sun_family=AF_UNIX;strcpy(sun.sun_path,"./unix");if(connect(sfd,(struct sockaddr*)&sun,sizeof(sun))<0){perror("connect");return -1;}char buf[128]="";while(1){//从终端获取输入memset(buf,0,sizeof(buf));printf("请输入>>");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]='\0';//发送给服务器send(sfd,buf,sizeof(buf),0);memset(buf,0,sizeof(buf));if(0==recv(sfd,buf,sizeof(buf),0)){printf("[%s]服务器下线\n",sun.sun_path);break;}printf("[%s]:%s\n",sun.sun_path,buf);}close(sfd);return 0;
}

报式域套接字服务器

#include <myhead.h>
//报式域套接字
int main(int argc, const char *argv[])
{//创建套接字int sfd=socket(AF_UNIX,SOCK_DGRAM,0);if(sfd<0){perror("socket");return -1;}//判断套接字文件是否存在,存在则删除if(access("./unix",F_OK)==0){if(unlink("./unix")!=0){perror("unlink");return -1;}}//填充地址信息结构体struct sockaddr_un sun;sun.sun_family=AF_UNIX;strcpy(sun.sun_path,"./unix");//绑定if(bind(sfd,(struct sockaddr *)&sun,sizeof(sun))<0){perror("bind");return -1;}//客户端地址信息结构体struct sockaddr_un cun;socklen_t addrlen=sizeof(cun);char buf[128]="";//接收发送while(1){//接收客户端信息memset(buf,0,sizeof(buf));if(recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cun,&addrlen)<0){perror("recvfrom");break;}printf("[%s]:%s\n",cun.sun_path,buf);strcat(buf,"*-*");if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cun,addrlen)<0){perror("sendto");break;}}close(sfd);return 0;
}

报式域套接字客户端

#include <myhead.h>
//报式域套接字
int main(int argc, const char *argv[])
{//创建套接字int cfd=socket(AF_UNIX,SOCK_DGRAM,0);if(cfd<0){perror("socket");return -1;}//判断套接字文件是否存在,存在则删除if(access("./linux",F_OK)==0){if(unlink("./linux")!=0){perror("unlink");return -1;}}//填充地址信息结构体struct sockaddr_un cun;cun.sun_family=AF_UNIX;strcpy(cun.sun_path,"./linux");//绑定if(bind(cfd,(struct sockaddr *)&cun,sizeof(cun))<0){perror("bind");return -1;}//服务器地址信息结构体struct sockaddr_un sun;sun.sun_family=AF_UNIX;strcpy(sun.sun_path,"./unix");socklen_t addrlen=sizeof(sun);char buf[128]="";//接收发送while(1){//从终端获取输入memset(buf,0,sizeof(buf));printf("请输入>>");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]='\0';//发送给服务器if(sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sun,addrlen)<0){perror("sendto");break;}//接收服务信息memset(buf,0,sizeof(buf));if(recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sun,&addrlen)<0){perror("recvfrom");break;}printf("%s\n",buf);}close(cfd);return 0;
}

tftp客户端

#include <myhead.h>
//tftp客户端
#define ERR_MSG(msg) do{fprintf(stderr,"__%d__",__LINE__);\perror(msg);\}while(0)
//#define IP "192.168.126.8"  //服务器IP地址
char IP[128];
#define PORT 69 			  //tftp服务器端口号69
// 下载
int download(int sfd);
//上传
int upload(int sfd);
int main(int argc, const char *argv[])
{//1.打开套接字int sfd = socket(AF_INET,SOCK_DGRAM,0);//从终端获取服务器IPprintf("server IP:");fgets(IP,sizeof(IP),stdin);IP[strlen(IP)-1]='\0';//2.绑定非必须while(1){puts("          \033[1;34;10m 1.下载");puts("          \033[1;34;10m 2.上传");puts("           3.退出\033[0m");printf("\033[1;32;10m请选择:\033[0m");int choice;scanf("%d",&choice);while(getchar()!=10);switch(choice){case 1:{ //下载	download(sfd);break;}case 2:{ //上传upload(sfd);break;}case 3:{ 	//退出goto end;			 break;}default:{ 	//其他break;}}printf("\033[1;33;10mpress space return menu or any key exit\033[0m");if(getchar()!=' '){break;}system("clear");}
end://4.关闭套接字close(sfd);return 0;
}//下载
int download(int sfd){//服务器地址信息结构体struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(PORT);sin.sin_addr.s_addr=inet_addr(IP);socklen_t len=sizeof(sin);//从终端获取文件名char fname[128]={0};fgets(fname,sizeof(fname),stdin);fname[strlen(fname)-1]='\0';//下载char buf[516]={0};short *p1=(short *)buf;//填充读写请求报文*p1=htons(1);                //1为读,2为写strcpy((buf+2),fname);char *p2=buf+2+strlen(fname);*p2='\0';strcpy((p2+1),"octet");*(p2+2+strlen("octet"))='\0';int size=4+strlen(fname)+strlen("octet");//发送下载请求if(sendto(sfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))<0){ERR_MSG("sendto");return -1;}printf("发送下载请求成功\n");int fd=-1;short hblock=0;while(1){memset(buf,0,sizeof(buf));//读取服务器数据包int res=recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&len);//获取服务器操作码short data=ntohs(*(short *)buf);//获取服务器发送的block编号short block=ntohs(*((short *)(buf+2)));//判断操作码3为数据包if(3==data){//判断有无丢包if(block==++hblock){//无丢包//当块编号为1时打开存储的文件if(1==block){fd=open(fname,O_WRONLY|O_CREAT|O_TRUNC,0664);if(fd<0){ERR_MSG("open");return -1;}}//把读取到的数据写入到本地文件if(write(fd,buf+4,res-4)<0){ERR_MSG("write");return -1;}//ack报文格式 操作码 块编号char ack[4];memset(ack,0,sizeof(ack));short *p1=(short *)ack;*p1=htons(4);             //操作码*(p1+1)=htons(block);     //块编号,无丢包直接回复收到的块编号//给服务器回ACKif(sendto(sfd,ack,sizeof(ack),0,(struct sockaddr*)&sin,sizeof(sin))<0){ERR_MSG("sendto");return -1;}//当数据包长度小于516,说明数据小于512,数据发送完毕if(res<516){printf("%s 下载完成\n",fname);break;}}else{//ack报文格式 操作码 块编号char ack[4];memset(ack,0,sizeof(ack));                                              short *p1=(short *)ack;*p1=htons(4);             //操作码*(p1+1)=htons(hblock);     //块编号,无丢包直接回复收到的块编号//给服务器回ACKif(sendto(sfd,ack,sizeof(ack),0,(struct sockaddr*)&sin,sizeof(sin))<0){ERR_MSG("sendto");return -1;}}}//5为错误包errorelse if(5==ntohs(*p2)){short err;err=ntohs(*(buf+2));printf("err=%d\n",err);break;}                                                                                }close(fd);
}
//上传
int upload(int sfd){//服务器地址信息结构体struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(PORT);sin.sin_addr.s_addr=inet_addr(IP);socklen_t len=sizeof(sin);//从终端获取文件名char fname[128]={0};fgets(fname,sizeof(fname),stdin);fname[strlen(fname)-1]='\0';//上传char buf[516]={0};short *p1=(short *)buf;//填充读写请求报文*p1=htons(2);                //1为读,2为写strcpy((buf+2),fname);char *p2=buf+2+strlen(fname);*p2='\0';strcpy((p2+1),"octet");*(p2+2+strlen("octet"))='\0';int size=4+strlen(fname)+strlen("octet");//发送上传请求if(sendto(sfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))<0){ERR_MSG("sendto");return -1;}printf("上传请求发送成功\n");//读取服务器应答  服务器允许上传则发送一个0号应答包char ack[128]={0};int res=recvfrom(sfd,ack,sizeof(ack),0,(struct sockaddr*)&sin,&len);if(res<0){ERR_MSG("recvfrom");return -1;}//获取服务器操作码short data=ntohs(*(short *)ack);//获取服务器发送的block编号short block=ntohs(*((short *)(ack+2)));//如果不允许上传直接返回if(block!=0) return -1;int fd=-1;short hblock=0;//打开要上传的文件fd=open(fname,O_RDONLY);if(fd<0){ERR_MSG("open");return -1;}			while(1){//清空bufmemset(buf,0,sizeof(buf));short *p1=(short *)buf;*p1=htons(3);                //操作码*(p1+1)=htons(++hblock);     //块编号,无丢包直接回复收到的块编号//把读取本地文件int res=read(fd,buf+4,512);if(res<0){ERR_MSG("read");return -1;}//给服务器发送数据包if(sendto(sfd,buf,4+res,0,(struct sockaddr*)&sin,sizeof(sin))<0){ERR_MSG("sendto");return -1;}//ack报文格式 操作码 块编号memset(ack,0,sizeof(ack));//当文件读取结束,上传完毕if(res==0){printf("%s 上传完成\n",fname);break;}while(1){//读取服务器应答res=recvfrom(sfd,ack,sizeof(ack),0,(struct sockaddr*)&sin,&len);if(res<0){ERR_MSG("recvfrom");return -1;}//获取服务器操作码data=ntohs(*(short *)ack);//获取服务器发送的block编号block=ntohs(*((short *)(ack+2)));//判断操作码4为服务器应答if(4==data){//判断有无丢包if(block==hblock){//无丢包break;				}//丢包重新发送当前包if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin))<0){ERR_MSG("sendto");return -1;}}	//5为错误包errorelse if(5==data){printf("err=%d\n",block);return -1;}}	}close(fd);
}

 思维导图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/623935.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

watchdog,监控文件变化的强大的python库

大家好&#xff0c;今天为大家分享一个无敌的 Python 库 - watchdog。 Github地址&#xff1a;github.com/gorakhargos… 在软件开发和系统管理领域&#xff0c;经常需要监控文件和目录的变化&#xff0c;以便在文件被创建、修改或删除时触发相应的操作。Python Watchdog是一…

BTC生态新贵Giants Planet:BTC L2如何与现实世界整合

前言 获新加坡主权基金鼎力扶持&#xff0c;Giants Planet将引爆Web3新风向。 随着年前BTC现货 ETF 的获批&#xff0c;加密世界涌入大量的资金&#xff0c;BTC价格也成功突破新高。与之相比&#xff0c;传统金融的弊端日益凸显&#xff0c;且大部分资产涨幅都低于BTC&#xf…

AI绘画分享 日漫男主背景自绘

用AI绘画可以生成各种各样我们曾经认为只能靠手工绘画的神奇的作品&#xff0c;包括以前一些日式的漫画画风也可以一键生成。今天我们就用AI绘画试试以前爆火的日漫男主的特写画风&#xff0c;看看AIGC的能力究竟有多强大&#xff01; 绘画准备 绘画思路&#xff1a;男主需以特…

招聘技术研发类岗位的人才测评方案

传统的招聘方式&#xff0c;无法顺应时代发展的趋势&#xff0c;通过职业测试去进行初步筛选&#xff0c;然后再确定是否进一步预约安排面试。下面就以技术公司为例&#xff0c;说是技术岗位的人才测评&#xff0c;应该考虑到哪些维度&#xff0c;也叫岗位胜任力模型的制定&…

【Qt 学习笔记】QWidget的windowOpacity属性 | cursor属性 | font属性

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ QWidget的windowOpacity属性 | cursor属性 | font属性 文章编号&#…

JavaScript零基础进阶2024详解

数组 JS中的数组相当于Java中的集合 数组长度可变 元素可变 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…

EditPlus简介、安装及详细配置

1. 引言 本章将介绍EditPlus文本编辑器的基本概述,并提供有关安装和配置EditPlus的详细步骤。EditPlus是一款功能强大的文本编辑器,提供了丰富的功能和定制选项,适用于各种编程语言和文件类型的编辑和开发工作。 2. EditPlus简介 EditPlus是一款由ES-Computing开发的文本…

深度学习基础——计算量、参数量和推理时间

深度学习基础——计算量、参数量和推理时间 在深度学习中&#xff0c;计算量、参数量和推理时间是评估模型性能和效率的重要指标。本文将介绍这三个指标的定义、计算方法以及如何使用Python进行实现和可视化展示&#xff0c;以帮助读者更好地理解和评估深度学习模型。 1. 定义…

代码随想录算法训练营第四十二天| 二维背包、一维背包、LeetCode 416.分割等和子集

一、二维背包 文章讲解/视频讲解&#xff1a;https://programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-1.html 状态&#xff1a;已解决 1.背包问题介绍 背包问题实则是一类问题的集合&#xff0c;有好多不同小类型&#xff0c…

Unity类银河恶魔城学习记录12-18,19 p140 Options UI-p141 Finalising ToolTip源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_ToolTip.cs using TMPro; using UnityEngine;public class UI_ToolTip :…

第十一章数据仓库和商务智能10分

【数据仓库-后端&#xff0c;商务智能-前端】 基本算法&#xff1a;关联关系&#xff08;牵手-谈恋爱&#xff09;&#xff0c;集群关系&#xff08;杭州人爱吃酸甜口&#xff09;&#xff0c;决策树&#xff0c;线性回归&#xff0c;贝叶斯&#xff0c;神经网络&#xff0c;时…

Vue3(二):报错调试,vue3响应式原理、computed和watch,ref,props,接口

一、准备工作调试 跟着张天禹老师看前几集的时候可能会遇到如下问题&#xff1a; 1.下载插件&#xff1a;Vue Language Features (Volar)或者直接下载vue-offical 2.npm run serve时运行时出现错误&#xff1a;Error: vitejs/plugin-vue requires vue (&#xff1e;3.2.13) …