Using both UDP and TCP to transfer data in one process

    UDP is a connectionless transmission, and datagrams may be lost during transmission, but UDP transmission is suitable for those situations where data is sent periodically with high real-time requirements. For example, the client periodically sends a fixed-length pulse signal to the server. Occasional loss of one or two packets of data will not cause a big problem. In this case, UDP can be used for transmission. Sometimes, the client also needs to send control commands to the server, but the control cannot be lost, then the TCP protocol needs to be used for transmission. The sample code below is to use both TCP and UDP to transfer data in one process.

/*=============================================================================
#     FileName: tcpudpselect.c
#         Desc: use tcp and udp to process client request
#       Author: Licaibiao
#   LastChange: 2017-02-12
=============================================================================*/
#include<stdio.h>  
#include<sys/types.h>  
#include<sys/socket.h>  
#include<unistd.h>  
#include<stdlib.h>  
#include<errno.h>  
#include<arpa/inet.h>  
#include<netinet/in.h>  
#include<string.h>  
#include<signal.h>
#define MAXLINE	  1024
#define LISTENLEN 10
#define SERV_PORT 6666

int max(int a, int b)
{
	return a>b ? a : b;
}

void sig_chld(int signo)
{
	pid_t	pid;
	int 	stat;
	while ((pid = waitpid(-1,stat,WNOHANG))>0)
	{	
		//printf("child %d terminated \n",pid);
	}
	return ;
}

void str_echo(int fd)
{

}


int main(int argc, char **argv)
{
	int				listenfd, connfd, udpfd, nready, maxfdp1;
	char				mesg[MAXLINE];
	pid_t				childpid;
	fd_set				rset;
	ssize_t				n;
	socklen_t len;
	const int			on = 1;
	struct sockaddr_in	cliaddr, servaddr;
	void				sig_chld(int);

	/* create listening TCP socket */
	listenfd = socket (AF_INET, SOCK_STREAM, 0);
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port        = htons(SERV_PORT);

	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
	bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr));
	listen(listenfd, LISTENLEN);

	/* create UDP socket */
	udpfd = socket (AF_INET, SOCK_DGRAM, 0);
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port        = htons(SERV_PORT);
	bind(udpfd, (struct sockaddr*) &servaddr, sizeof(servaddr));

	signal(SIGCHLD, sig_chld);	/* must call waitpid() */

	FD_ZERO(&rset);
	maxfdp1 = max(listenfd, udpfd) + 1;
	for ( ; ; )
	{
		FD_SET(listenfd, &rset);
		FD_SET(udpfd, &rset);
		if ( (nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0)
		{
			if (errno == EINTR)
				continue;		/* back to for() */
			else
			{
				printf("select error");
				exit(0);
			}
		}

		if (FD_ISSET(listenfd, &rset))
		{
			len = sizeof(cliaddr);
			connfd = accept(listenfd, (struct sockaddr*) &cliaddr, &len);
	
			if ( (childpid = fork()) == 0) /* child process */
			{	
				close(listenfd);	/* close listening socket */
				str_echo(connfd);	/* process the request */
				exit(0);
			}
			close(connfd);			/* parent closes connected socket */
		}

		if (FD_ISSET(udpfd, &rset))
		{
			len = sizeof(cliaddr);
			n = recvfrom(udpfd, mesg, MAXLINE, 0, (struct sockaddr*) &cliaddr, &len);

			sendto(udpfd, mesg, n, 0, (struct sockaddr*) &cliaddr, len);
		}
	}
}
We call the select function to listen for TCP and UDP readability conditions, and then the TCP connection creates a new process to handle. Strictly speaking, it is not actually handled by a process.

Here we use the same port for both TCP and UDP. In TCP/UDP, a 5-tuple is used to locate a connection, src_ip, src_port, dest_ip, dest_port, protocol_type, where the protocol_type is different, so even if they use the same port number, they will not conflict.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324756196&siteId=291194637