Aplicación básica de UDP y caso de transmisión

Tabla de contenido

Modelo de servidor cliente UDP

transmisión de datos

enviar datos

Aceptar datos

Código del programa del servidor

Código del programa del cliente

transmisión

Receptor de radiodifusión

Remitente de la transmisión

Modelo de servidor cliente UDP

transmisión de datos

enviar datos

#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t nbytes, int flag);
  • Retorno: Devuelve el número de bytes enviados si tiene éxito y -1 si se produce un error.
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flag);
  • Retorno: Devuelve el número de bytes enviados si tiene éxito y -1 si se produce un error.
ssize_t sendto(int sockfd, const void *buf, size_t nbytes, int flag,
                const struct sockaddr *destaddr, socklen_t destlen);
  • Retorno: Devuelve el número de bytes enviados si tiene éxito y -1 si se produce un error.
struct msghdr{
    void *msg_name; /*optional address*/
    socklen_t msg_namelen; /*address size in bytes*/
    struct iovec *msg_iov; /*array of I/O buffers*/
    int msg_iovlen; /*number of elements in array */
    void *msg_control; /*ancillary data*/
    socklen_t msg_controllen; /*number of ancillary bytes*/
    int msg_flags; /*flags for received message*/
}

Aceptar datos

#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t nbytes, int flag);
ssize_t recvfrom(int sockfd, void *restrict buf, size_t len, int flag,
                struct sockaddr *restrict addr, socklen_t *restrict addrlen);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flag);
  • Retorno: Devuelve el número de bytes del mensaje, 0 si no hay mensaje, -1 si hay error

Código del programa del servidor

int sockfd; 
void sig_handler(int signo)
{
	if(signo==SIGINT)
	{
		printf("server close\n"); 
		close(sockfd); 
		exit(1);
	}
}

//输出客户端的信息
void out_addr(struct sockaddr_in* clientaddr)
{
	char ip[16];
	memset(ip,0,sizeof(ip));
	inet_ntop(AF_INET, &clientaddr->sin_addr.s_addr,ip, sizeof(ip));
	int port=ntohs(clientaddr->sin_port);
	printf("client:%s(%d)\n", ip, port);
}

//和客户端进行通信
void do_service(int fd)
{
	struct sockaddr_in clientaddr;
	socklen_t len = sizeof(clientaddr);
	
	char buffer[1024];
	memset(buffer, 0, sizeof(buffer));
	
	//接受客户端的数据报文
	if(recvfrom(sockfd,buffer, sizeof(buffer), 0,
				(struct sockaddr*)&clientaddr, &len)<0)
	{
		perror("recvfrom error");
	}
	else
    {		
		out_addr(&clientaddr);
		printf("client send info:%s\n", buffer);
		
		//向客户端发送数据报文
		long int t =time(0);
		char*ptr = ctime(&t);
		
		size_t size = strlen(ptr)*sizeof(char);
		if(sendto(sockfd, ptr, size, 0, \
			(struct sockaddr*)&clientaddr, len)<0)
		{
			perror("sendto error"); 			
		}
	}
}

int main(int argc, char *argv[])
{
	if(argc<2)
	{
		printf("usage:%s port\n",argv[0]); 
		exit(1); 
	}
	
	if(signal(SIGINT, sig_ handler) == SIG_ERR)
	{
		perror("signal sigint error"); 
		exit(1);
	}
	
	/*步骤1:创建 socket*/
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd < 0)
	{
		perror("socket error");
		exit(1);
	}

	int ret;
	int opt=1;
	//设置套接字选项
	if((ret=setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, \
						sizeof(opt)))<0)
	{
		perror("setsockopt error");
		exit(1);
	}
	
	/*步骤2:调用bind函数对socket和地址进行绑定*/
	struct sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;//IPV4
	serveraddr.sin_port = htons(atoi(argv[1]));//port 
	serveraddr.sin_addr.s_addr = INADDR_ANY;//ip 
	
	if(bind(sockfd, (struct sockaddr*)&serveraddr, \
					sizeof(serveraddr))<0)
	{
		perror("bind error");
		exit(1);
	}

	/*步骤3:和客户端进行双向的数据通信*/
	while(1){
		do_service();
		return 0;
	}	
}

Código del programa del cliente

int main(int argc,char *argv[])
{
	if(argc < 3)
	{
		printf("usage:%s ip port\n", argv[0]); 
		exit(1);
	}

	/*步骤1:创建 socket*/
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd < 0)
	{
		perror("socket error");
		exit(1);
	}

	/*步骤2:调用recvfrom和sendto等函数
	*和服务器端双向通信
	*/
	struct sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;//IPV4
	serveraddr.sin_port = htons(atoi(argv[1]));//port 
	serveraddr.sin_addr.s_addr = INADDR_ANY;//ip 

	if(connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
	{
		perror("connect error"); 
		exit(1);
	}

	char buffer[1024] = "Hello world!";
	//向服务器端发送数据报文
	//if(sendto(sockfd, buffer, sizeof(buffer), 0,\
	//		(struct sockaddr*)&serveraddr,sizeof(serveraddr)) < 0)
	if(sendto(sockfd, buffer, sizeof(buffer), 0) < 0)
	{
		perror("sendto error");
		exit(1);
	}
	else
	{
		//接受服务器端发送的数据报文
		memset(buffer, 0, sizeof(buffer));
		size_t size;
		
		if(recv(sockfd, buffer, sizeof(buffer), 0) <0 )
		{
			perror("recv error");
			exit(1);
		}
		else
		{
			printf("%s",buffer); 			
		}
	}
	close(sockfd);
	
	return 0;
}

transmisión

  • La opción SO_BROADCAST controla si un socket UDP puede enviar datagramas de difusión. El tipo de la opción es int y distinto de cero significa "sí". Tenga en cuenta que solo los sockets UDP pueden utilizar esta opción y TCP no puede utilizar la difusión.
int opt = 1;
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
//错误处理
}
if(setsockopt(sockfd, SOL_SOCKET,
    SO_BROADCAST, &opt, sizeof(opt)) < 0)
{
//错误处理
}

Receptor de radiodifusión

int sockfd; 
void sig_handler(int signo)
{
	if(signo==SIGINT)
	{
		printf("server close\n"); 
		close(sockfd); 
		exit(1);
	}
}

int main(int argc, char *argv[])
{
	if(argc<2)
	{
		printf("usage:%s port\n",argv[0]); 
		exit(1); 
	}
	
	if(signal(SIGINT, sig_handler) == SIG_ERR)
	{
		perror("signal sigint error"); 
		exit(1);
	}
	
	/*步骤1:创建 socket*/
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd < 0)
	{
		perror("socket error");
		exit(1);
	}

	/*步骤2:调用bind函数对socket和地址进行绑定*/
	struct sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;//IPV4
	serveraddr.sin_port = htons(atoi(argv[1]));//port 
	serveraddr.sin_addr.s_addr = INADDR_ANY;//ip 
	
	if(bind(sockfd, (struct sockaddr*)&serveraddr, \
					sizeof(serveraddr))<0)
	{
		perror("bind error");
		exit(1);
	}

	char buffer[1024]; 
	struct sockaddr_in clientaddr; 
	socklen_t len=sizeof(clientaddr); 
	
	while(1){
		memset(buffer, 0, sizeof(buffer)); 
		memset(&clientaddr, 0, sizeof(clientaddr)); 
		if(recvfrom(sockfd, buffer, sizeof(buffer),0,\
				(struct sockaddr*)&clientaddr, &len)<0)
		{
			perror("recvfrom error"); 
			exit(1);
		} 
		else
		{
			char ip[16]; 
			inet_ntop(AF_INET, &clentaddr.sin_addr.s_addr, ip, sizeof(ip)); 
			int port=ntohs(clientaddr.sin_port); 
			printf("%s(%d):%s\n", ip, port, buffer);
		}
	}	
	close(sockfd);	
	return 0;	
}

Remitente de la transmisión

int sockfd; 

int main(int argc, char *argv[])
{
	if(argc<2)
	{
		printf("usage:%s port\n", argv[0]); 
		exit(1); 
	}
	
	/*步骤1:创建 socket*/
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd < 0)
	{
		perror("socket error");
		exit(1);
	}

	int opt=1;//采用广播方式发送
	setsockopt(sockfd, SOL_SOCKET,SO_BROADCAST, &opt, sizeof(opt));
	
	struct sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(serveraddr));
	serveraddr.sin family=AF_INET;
	serveraddr.sin_port = htons(atoi(argv[2]));
	inet_pton(AF_INET, argv[1], &serveraddr.sin_addr.s_addr);
	
	printf("I will broadcast...\n"); 
	char * info="hello iotek"; 
	size_t size=strlen(info)* sizeof(char);
	
	if(sendto(sockfd, info, size,0,
			(struct sockaddr*)&serveraddr, sizeof(serveraddr))<0)
	{ 
		perror("sendto error"); 
		exit(1);
	} 
	else
	{
		printf("boradcast success\n");
	}
	
	close(sockfd);
	
	return 0;	
}

 

Supongo que te gusta

Origin blog.csdn.net/baidu_41388533/article/details/111707198
Recomendado
Clasificación