网络编程day04(网络属性函数、广播、组播、TCP并发)

2023-09-21 22:19:49

今日任务

对于newfd的话,最好是另存然后传入给分支线程,避免父子线程操作同一个文件描述符

1.广播:

接收端

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
 #include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>



#define ERR_MSG(msg) do{\
	perror(msg);\
	fprintf(stderr,"__%d__",__LINE__);\
}while(0)
#define IP "192.168.125.255"
#define PORT 8888
/*
 * function:    广播,接收方
 * @param [ in] 
 * @param [out] 
 * @return      
 */

int main(int argc, const char *argv[])
{
	//创建报式套接字
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd<0){
		ERR_MSG("socket");
		return -1;
	}
	puts("socket success");
	//绑定IIF(P和端口号(广播ip)
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(PORT);
	addr.sin_addr.s_addr=inet_addr(IP);
	socklen_t addrlen=sizeof(addr);
	if(bind(sfd,(struct sockaddr*)&addr,addrlen)<0){
		ERR_MSG("bind");
	}
	puts("bind success");
	//存储发送方地址消息
	struct sockaddr_in source_addr;
	socklen_t source_addrlen=sizeof(source_addr);
	//循环接受消息
	char buf[128]="";
	while(1){
		bzero(buf,sizeof(buf));
		int recv_res=recvfrom(sfd,&buf,sizeof(buf),0,(struct sockaddr*)&source_addr,&source_addrlen);
		if(recv_res<0){
			ERR_MSG("recvfrom");
			return -1;
		}
		puts("recvfrom success");
		printf("[%s:%d]:%s\n",inet_ntoa(source_addr.sin_addr),ntohs(source_addr.sin_port),buf);
	}
	//关闭
	close(sfd);
	return 0;
}

发送端

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
 #include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>



#define ERR_MSG(msg) do{\
	perror(msg);\
	fprintf(stderr,"__%d__",__LINE__);\
}while(0)
#define IP "192.168.125.255"
#define PORT 8888
/*
 * function:    广播,发送方
 * @param [ in] 
 * @param [out] 
 * @return      
 */

int main(int argc, const char *argv[])
{
	//创建报式套接字
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd<0){
		ERR_MSG("socket");
		return -1;
	}
	puts("socket success");
	//设置允许广播
	int optval=1;//非0为允许
	socklen_t optlen=sizeof(optval);
	if(setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&optval,optlen)<0){
		ERR_MSG("setsockopt");
		return -1;
	}

	//IP和端口号(广播ip)
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(PORT);
	addr.sin_addr.s_addr=inet_addr(IP);
	socklen_t addrlen=sizeof(addr);
	//循环发送消息
	char buf[128]="";
	while(1){
		bzero(buf,sizeof(buf));
		printf("请输入>>>");
		fgets(buf,sizeof(buf),stdin);
		buf[strlen(buf)-1]='\0';
		if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&addr,addrlen)<0){
			ERR_MSG("sendto");
			return -1;
		}
		puts("sendto success");
		}
	//关闭
	close(sfd);
	return 0;
}

2.组播

接收端

代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>                                                                   
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>

#define ERR_MSG(msg) do{\
	perror(msg);\
	fprintf(stderr,"__%d__",__LINE__);\
}while(0)
#define IP "192.168.125.2"
#define PORT 8888
#define GRP_IP "224.1.2.3"
/*
 * function:    组播:接收方
 * @param [ in] 
 * @param [out] 
 * @return      
 */
int main(int argc, const char *argv[])
{
	//创建报式套接字
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd<0){
		ERR_MSG("socket");
		return -1;
	}
	puts("socket success");

	//加入多播组
	struct ip_mreqn mq;

    mq.imr_multiaddr.s_addr = inet_addr(GRP_IP);    //组播IP
    mq.imr_address.s_addr   = inet_addr(IP);    //本机IP,ifconfig
    mq.imr_ifindex = 2;         //网络设备索引号

	if(setsockopt(sfd,IPPROTO_IP, IP_ADD_MEMBERSHIP,&mq,sizeof(mq))<0){
		ERR_MSG("setsockopt");
		return -1;
	}


	//绑定IIF(P和端口号(广播ip)
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(PORT);
	addr.sin_addr.s_addr=inet_addr(GRP_IP);
	socklen_t addrlen=sizeof(addr);
	if(bind(sfd,(struct sockaddr*)&addr,addrlen)<0){
		ERR_MSG("bind");
	}
	puts("bind success");


	//接受对方地址信息
	struct sockaddr_in source_addr;
	socklen_t source_addrlen=sizeof(source_addr);

	char buf[128]="";

	while(1){
	
		//接收消息
		bzero(buf,sizeof(buf));
		int recv_res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&source_addr, &source_addrlen);
        if(recv_res < 0)
        {
            ERR_MSG("recvfrom");
            return -1;
        }

        printf("[%s:%d] : %s\n", \
                inet_ntoa(source_addr.sin_addr), ntohs(source_addr.sin_port), buf);
	}
	//关闭
	close(sfd);
	return 0;
}

发送端

代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>                                                                   
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>

#define ERR_MSG(msg) do{\
	perror(msg);\
	fprintf(stderr,"__%d__",__LINE__);\
}while(0)
#define IP "192.168.125.2"
#define PORT 8888
#define GRP_IP "224.1.2.3"
/*
 * function:    组播:发送方
 * @param [ in] 
 * @param [out] 
 * @return      
 */
int main(int argc, const char *argv[])
{
	//创建报式套接字
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd<0){
		ERR_MSG("socket");
		return -1;
	}
	puts("socket success");

	//绑定IIF(P和端口号(广播ip)
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(PORT);
	addr.sin_addr.s_addr=inet_addr(GRP_IP);
	socklen_t addrlen=sizeof(addr);
	if(bind(sfd,(struct sockaddr*)&addr,addrlen)<0){
		ERR_MSG("bind");
	}
	puts("bind success");



	char buf[128]="";

	while(1){
	
		//发送消息
		bzero(buf,sizeof(buf));
		  printf("请输入>>> ");
        fgets(buf, sizeof(buf), stdin);
        buf[strlen(buf)-1] = 0;

        //发送数据, 主动发送给指定接收放,例如这里可以主动发给接收方
        if(sendto(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0)
        {
            ERR_MSG("sendto");
            return -1;
        }
        printf("sendto success\n");
		}
	//关闭
	close(sfd);
	return 0;
}

3.TCP并发

多线程

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
//自定义报错提示
#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__",__LINE__);\
	perror(msg);\
}while(0)
#define SER_PORT 8888
#define SER_IP "192.168.125.2"
/*
 * function:    TCP服务端
 * @param [ in] 
 * @param [out] 
 * @return      
 */

int recv_send(int cfd,struct sockaddr_in cli_addr);
void handle(int sig){
	while(waitpid(-1,NULL,WNOHANG)>0);
	return ;
}

int main(int argc, const char *argv[])
{
	//监听回收僵尸进程
	if(signal(SIGCHLD,handle)==SIG_ERR){
		ERR_MSG("signal");
		return -1;
	}

	//1.创建socket套接字,
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0){
		ERR_MSG("socket");
		return -1;
	}
	puts("socket create");

	//允许端口快速复用
	int reuse = 1;
	if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		ERR_MSG("setsockopt");
		return -1;
	}
	printf("允许端口快速复用成功\n");
	//2.绑定服务器IP和端口号bind
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(SER_PORT);
	addr.sin_addr.s_addr=inet_addr(SER_IP);
	if(bind(sfd,(struct sockaddr*)&addr,sizeof(addr))<0){
		ERR_MSG("bind");
		return -1;
	}
	puts("bind success");


	//3.建立监听listen
	if(listen(sfd,128)<0){
		ERR_MSG("listen");
		return -1;
	}
	puts("listen suucess");


	//4.等待客户端连接, accept
	struct sockaddr_in cli_addr;
	socklen_t cli_addrlen=sizeof(cli_addr);
	pid_t pid;
	while(1){
		int cfd=accept(sfd,(struct sockaddr*)&cli_addr,&cli_addrlen);
		if(cfd<0){
			ERR_MSG("accept");
			return -1;
		}
		puts("accept");
		pid=fork();
		if(pid==0){
			//子进程执行信息收发
			recv_send(cfd,cli_addr);
			exit(0);
		}else if(pid<0){
			ERR_MSG("fork");
			return -1;
		}
		close(cfd);

	}
	//6.关闭
	close(sfd);


	return 0;
}
int recv_send(int cfd,struct sockaddr_in cli_addr){
	//5.接受发送消息recv;send
	char buf[128];
	while(1){
		bzero(buf,sizeof(buf));
		int recv_res=recv(cfd,buf,sizeof(buf),0);

		if(recv_res<0){
			ERR_MSG("recv");
			return -1;
		}else if(recv_res==0){
			printf("socket peer has shutdown\n");
			break;
		}
		puts("recv success");
		printf("[%s:%d]:%s\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
		if(strcmp(buf,"quit")==0)
			break;

		strcat(buf,"-----i has received");
		int send_res=send(cfd,buf,sizeof(buf),0);
		if(send_res<0){
			ERR_MSG("send");
			return -1;
		}
		puts("send success");
	}
}

多进程

代码:

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

//自定义报错提示
#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__",__LINE__);\
	perror(msg);\
}while(0)
#define SER_PORT 8888
#define SER_IP "192.168.125.2"
struct cliMsg{
	int cfd;
	struct sockaddr_in cli_addr;
};
/*
 * function:    TCP服务端
 * @param [ in] 
 * @param [out] 
 * @return      
 */
void* recv_send(void*arg);
int main(int argc, const char *argv[])
{
	//1.创建socket套接字,
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0){
		ERR_MSG("socket");
		return -1;
	}
	puts("socket create");

	//允许端口快速复用
	int reuse = 1;
	if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		ERR_MSG("setsockopt");
		return -1;
	}
	printf("允许端口快速复用成功\n");
	//2.绑定服务器IP和端口号bind
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(SER_PORT);
	addr.sin_addr.s_addr=inet_addr(SER_IP);
	if(bind(sfd,(struct sockaddr*)&addr,sizeof(addr))<0){
		ERR_MSG("bind");
		return -1;
	}
	puts("bind success");


	//3.建立监听listen
	if(listen(sfd,128)<0){
		ERR_MSG("listen");
		return -1;
	}
	puts("listen suucess");


	//4.等待客户端连接, accept
	struct sockaddr_in cli_addr;
	socklen_t cli_addrlen=sizeof(cli_addr);
	pthread_t pth;
	while(1){

		int cfd=accept(sfd,(struct sockaddr*)&cli_addr,&cli_addrlen);
		if(cfd<0){
			ERR_MSG("accept");
			return -1;
		}
		puts("accept");
		struct cliMsg climsg;
		climsg.cfd=cfd;
		climsg.cli_addr=cli_addr;
		//创建调用线程执行
		if(pthread_create(&pth,NULL,recv_send,(void *)&climsg)!=0){
			fprintf(stderr,"pthread_create failed __%d__\n",__LINE__);
			return -1;
		}
		pthread_detach(pth);

	}
	close(sfd);

	return 0;
}
void* recv_send(void*arg){
	//5.接受发送消息recv;send
	int cfd=((struct cliMsg*)arg)->cfd;
	struct sockaddr_in cli_addr=((struct cliMsg*)arg)->cli_addr;

	char buf[128];
	while(1){
		bzero(buf,sizeof(buf));
		int recv_res=recv(cfd,buf,sizeof(buf),0);

		if(recv_res<0){
			ERR_MSG("recv");
			 break;
		}else if(recv_res==0){
			printf("socket peer has shutdown\n");
			break;
		}
		puts("recv success");
		printf("[%s:%d]:%s\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
		if(strcmp(buf,"quit")==0)
			break;

		strcat(buf,"-----i has received");
		int send_res=send(cfd,buf,sizeof(buf),0);
		if(send_res<0){
			ERR_MSG("send");
			break;
		}
		puts("send success");
	}
	close(cfd);
	pthread_exit(NULL);
}

今日思维导图

不知道最近确实是脑子比较慢,还是拖拉,做事太慢了,tcp的代码还没复敲;

更多推荐

4k、VR与万兆光网

“全光万兆”对VR意义重大。pico4的分辨率PICO4的单眼分辨率是2160×2160,整体分辨率高达4320×2160。这是一款高性能的VR一体机,采用了2.56英寸的Fast-LCD屏幕,最高可实现90Hz刷新率,还有1200PPI和20.6PPD的超清晰画面表现。PICO4的视场角为105°,比上一代PICON

使用HTTP爬虫ip中的常见误区与解决方法

在使用HTTP爬虫进行网页抓取时,涉及到IP地址的处理,可能会存在一些常见的误区。以下是一些常见误区及解决方法:1.使用个人IP进行大规模爬取:如果你使用个人住宅IP进行大规模爬取,可能会被目标网站视为恶意攻击,从而导致被封禁。解决方法:使用代理IP,或者租用专门的爬虫服务器。2.忽略IP封禁:一些网站可能会封禁特定的

Android kotlin系列讲解(进阶篇)解析XML格式数据

点击查看>返回总目录<|上一篇:Androidkotlin系列讲解(入门篇)使用HTTP访问网络文章目录1、Pull解析方式2、SAX解析方式通常情况下,每个需要访问网络的应用程序都会有一个自己的服务器,我们可以向服务器提交数据,也可以从服务器上获取数据。不过这个时候就出现了一个问题,这些数据到底要以什么样的格式在网络

Kotlin 不可变数组和可变数组

在Kotlin中,可以使用数组来存储一组相同类型的元素。Kotlin提供了两种类型的数组:不可变数组和可变数组。不可变数组(ImmutableArrays)不可变数组的大小(元素数量)在创建后就确定,并且不能更改。使用arrayOf()函数或者arrayOfNulls()函数创建不可变数组。不可变数组中的元素值是固定的

2023年日经225指数研究报告

第一章指数概况1.1概述日经225指数,又被称为日经平均股票价格或日经225平均指数,通常被称为日经或日经指数,是东京证券交易所的一个重要股价指数。该指数自1950年起由日本经济新闻(TheNikkei)日报计算,它是一个以价格为权重的指数,以日元(JP¥)为单位,其组成部分每年审查一次。该指数涵盖了东京证券交易所第一

Git标签管理:从创建到推送的完整指南

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🦄博客首页——🐅🐾猫头虎的博客🎐🐳《面试题大全专栏》🦕文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》🐾学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》🐅学会Gol

RabbitMQ - 消息堆积问题的最佳解决方案?惰性队列

目录一、惰性队列1.1、消息堆积问题1.2、消息堆积问题的解决方法从消费者的角度:从队列的角度:1.3、引入惰性队列1.3.1、什么是惰性队列1.3.2、惰性队列的使用1.3.3、效果演示一、惰性队列1.1、消息堆积问题当生产者发送消息的速度超过了消费者处理消息的速度,就会导致队列中的消息堆积,直到队列存储消息到达上限

滴滴可观测平台 Metrics 指标实时计算如何实现了又准又省?

在滴滴,可观测平台的Metrics数据有一些实时计算的需求,承载这些实时计算需求的是一套又一套的Flink任务。之所以会有多套Flink任务,是因为每个服务按照其业务观测需要不同的指标计算,也就对应了不同数据处理拓扑。我们尽力抽象用户相同的计算需求,不过由于Flink实时计算任务开发模式和实时计算框架的限制,这些观测指

专业软件测评中心:关于软件性能测试的实用建议

软件性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。性能测试在软件的质量保证中起着重要的作用,它包括的测试内容丰富多样。一、软件性能测试的实用建议1、制定清晰的测试目标:明确测试目标和需求,以便更好地组织测试活动。2、选择合适的测试工具:根据测试需求选择适合的性能测试工具

支付宝支付对接-附带完整代码!!

支付宝对接文章目录支付宝对接1、大纲1.1整体业务流程图1.2、开发流程图1.3、核心参数1.4、支付宝开放平台1.5、支付应用场景1.6、支付宝入驻2、环境准备2.1首先注册自己的支付宝账号2.2沙箱环境2.3支持产品列表3、项目实现3.1、项目代码地址3.2、代码层级3.3、快速启动3.3.1环境准备3.3.2定义

PTA:L1-002 打印沙漏

L1-002打印沙漏分数20本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印*****************所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。给定任意N个符号,不一定

热文推荐