Linux Network programming: Set non-blocking Socket transceiver Data __ block chain

Source: Internet
Author: User
Tags readable sleep function socket error

Non-blocking I/O includes non-blocking input operations, non-blocking output operations, non-blocking receiving foreign connections, non-blocking initiating outgoing connections. The functions included are: Read, Readv, recv, Recvfrom, Recvmsg, write, Writev, send, SendTo, sendmsg, accept.

There are three general ways to set the socket to non-blocking mode:

(1) When creating a socket, specify that the socket is asynchronous and set the SOCK_NONBLOCK flag in the parameter of type.

int socket (int domain, int type, int protocol);
int s = socket (af_inet, Sock_stream | Sock_nonblock, IPPROTO_TCP);
(2) using the FCNTL function:

Fcntl (SOCKFD, F_SETFL, Fcntl (SOCKFD, F_GETFL, 0) | O_nonblock);
(3) using the IOCTL function:

IOCTL (SOCKFD, Fionbio, 1);  1: Non-blocking 0: Blocking
The following rewrite Linux network programming: The use of multiple processes to implement the socket at the same time send and receive data in the program

/*============================================================================= # filename:nonblocktcp.c # De Sc:set the CONNETFD unblock # author:licaibiao # lastchange:2017-02-14 ======================================= ======================================*/#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> #include <fcntl.h> #define


Maxline 256 #define PORT 6666 void process_out (int signo) {exit (exit_success);}
	
	void Write_func (int pid, int fd) {char* write = "I am Server";

	printf ("Write id =%d\n", PID);  
	Signal (sigusr1,process_out);
		while (1) {sleep (1);
	Send (Fd,write,strlen (write) +1,0);
	} void Read_func (int pid, int fd) {char readbuff[maxline];

	int n = 0;

	printf ("Read id =%d \ n", PID); memset (&readbuff,0,siZeof (Readbuff)); 
		while (1) {n = recv (fd, Readbuff, maxline, 0);
		if (n > 0) {printf ("Server recv data:%s \ n", Readbuff);
		else if (n = = 0) {break;
		Sleep (1);
	printf ("===\n");
	
	};
	printf ("Exit read function\n"); 
	Kill (PID, SIGUSR1);
Exit (exit_success);
	int main (void) {int listenfd,connetfd;
	int on = 1;
	int addrlen = 0;
	int flags;
	pid_t pid, Pid_child, Pid_send;
	struct sockaddr_in server_addr;


	struct sockaddr_in client_addr;
	if ((LISTENFD = socket (pf_inet, Sock_stream, ipproto_tcp)) < 0) {printf ("Create socket ERR \ n");
	} addrlen = sizeof (struct sockaddr_in);
	memset (&server_addr, 0, Addrlen);    
	server_addr.sin_family = af_inet; 
	SERVER_ADDR.SIN_ADDR.S_ADDR = htonl (Inaddr_any); 

	Server_addr.sin_port = htons (port); if (setsockopt (LISTENFD, Sol_socket, so_reuseaddr, &on, sizeof (ON)) < 0) {printf (bind SOCKET Error:%s (ERRN
		O:%d) \ n ", Strerror (errno), errno);
	Exit (0); } if (Bind LISTENFD, (sTruct sockaddr*) &server_addr, sizeof (SERVER_ADDR)) = = 1) {printf (Bind socket Error:%s (errno:%d) \ n ", Strerror (er
		Rno), errno);
	Exit (0);
		} if (listen (LISTENFD) = = 1) {printf ("Listen socket Error:%s (errno:%d) \ n", Strerror (errno), errno);
	Exit (0);
	printf ("Wait client accpt \ n"); while (1) {if (Connetfd = Accept (LISTENFD, (struct sockaddr*) &client_addr, &addrlen)) = = = 1) {printf (
			"Accept Socket Error:%s (errno:%d)", Strerror (errno), errno);
		Continue
		}/* Set nonblock/flags = FCNTL (CONNETFD, F_GETFL, 0); Fcntl (CONNETFD, F_SETFL, Flags |

		O_nonblock);
		Signal (SIGCHLD, sig_ign);
		PID = fork ();
		if (PID = = 1) {printf ("Fork err \ n"); 
			} if (pid = = 0) {pid_child = fork (); 	
				if (Pid_child = = 0) {pid_send = Getpid ();
			Read_func (Pid_send, CONNETFD); 	
				else {pid_send = Getpid ();
			Write_func (PID_SEND,CONNETFD); }
		}

	}
}
In this program, when a connection to a client is received, the connection descriptor is set to non-blocking:

		Flags = FCNTL (CONNETFD, F_GETFL, 0);
		Fcntl (CONNETFD, F_SETFL, Flags | O_nonblock);

After this setting, both the Send and RECV functions in read and write functions become non-blocking mode. Here we are using sleep to do a delay loop to detect data readable and data can be sent. The common socket timeout here is not the sleep function. We can use the following three socket timeout methods.

Socket Timeout:

(1) Call alarm, which produces a sigalarm signal when the specified timeout expires, similar to the Linux signal processing.

static void Sig_alrm (int signo)
{return
	;			/* Just interrupt the recvfrom ()/
}

void Dg_cli (FILE *fp, int sockfd, const SA *pservaddr, socklen_t Servlen) 
  {
	int	n;
	Char	Sendline[maxline], recvline[maxline + 1];

	Signal (SIGALRM, SIG_ALRM);

	while (Fgets (Sendline, Maxline, FP)!= NULL) {

		sendto (sockfd, Sendline, strlen (Sendline), 0, pservaddr, Servlen); 
  alarm (5);
		if ((n = recvfrom (SOCKFD, Recvline, maxline, 0, NULL, NULL)) < 0) {
			if (errno = = eintr)
				fprintf (stderr, "Soc Ket timeout\n ");
			else
				err_sys ("Recvfrom error");
		} else {
			alarm (0);
			Recvline[n] = 0;	/* NULL Terminate *
			/fputs (Recvline, stdout);
		}}

(2) block wait I/O (select has built-in time limit) in the select instead of blocking directly on read or write calls.

int readable_select (int fd, int sec)
{
	fd_set			rset;
	struct TIMEVAL	TV;

	Fd_zero (&rset);
	Fd_set (FD, &rset);

	Tv.tv_sec = sec;
	tv.tv_usec = 0;

	Return (select (fd+1, &rset, NULL, NULL, &TV));
		/* 4> 0 if descriptor is readable */
}

(3) Use newer So_rcvtimeo and So_sndtimeo socket options.

void Dg_cli (FILE *fp, int sockfd, const SA *pservaddr, socklen_t Servlen)
{
	int				n;
	Char			Sendline[maxline], recvline[maxline + 1];
	struct TIMEVAL	TV;

	Tv.tv_sec = 5;
	tv.tv_usec = 0;
	SetSockOpt (SOCKFD, Sol_socket, So_rcvtimeo, &TV, sizeof (TV));

	while (Fgets (Sendline, Maxline, FP)!= NULL) {

		sendto (sockfd, Sendline, strlen (Sendline), 0, pservaddr, Servlen); 
  n = Recvfrom (SOCKFD, Recvline, maxline, 0, NULL, NULL);
		if (n < 0) {
			if (errno = = Ewouldblock) {
				fprintf (stderr, "Socket timeout\n");
				Continue;
			} else
				err_sys ("Recvfrom error");
		}

		Recvline[n] = 0;	/* NULL Terminate *
		/fputs (Recvline, stdout);
	}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.