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

今日任务

网络编程day04(网络属性函数、广播、组播、TCP并发)_第1张图片

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

------------在tcp多线程服务端----------

如果使用全局变量,或者指针方式间接访问,会导致所有线程共用一份newfd和cin,那么newfd和cin会被覆盖

1.广播:

接收端

代码:

#include 
#include 
#include 
#include           /* See NOTES */
#include 
 #include 
#include 
#include 



#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 
#include 
#include 
#include           /* See NOTES */
#include 
 #include 
#include 
#include 



#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 
#include 
#include 
#include                                                                    
#include 
#include 
#include 

#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 
#include 
#include 
#include                                                                    
#include 
#include 
#include 

#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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
//自定义报错提示
#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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

//自定义报错提示
#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的代码还没复敲;

你可能感兴趣的:(网络,tcp/ip,网络协议)