Linux Network programming: use two threads to implement the socket simultaneously send and receive data __ block chain

Source: Internet
Author: User
Tags sigint signal socket error htons

There is a recent use of the socket to send and receive data to the client at the same time, because it is an embedded Linux device and requires only one client to connect to the port at a time. Given the savings in system resources, only two threads were created to implement the service-side transceiver data. Directly below the code, the code for the PC on the program, has made detailed comments.

Server.c

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/ types.h> #include <sys/socket.h> #include <netinet/in.h> #include <termios.h> #include <sys/ types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h&gt
;
#include <signal.h> #define MAXLINE 256 #define PORT 6666 int listenfd;
int CONNFD;

pthread_t read_id, write_id;
	/* Linux CTRL + C generates SIGINT signals to receive SIGINT signals into the function/void stop (int signo) {printf ("stop\n");	
	Close (CONNFD);
	 Close (LISTENFD);
_exit (0);
/* * When the client disconnects, the thread that receives the sigpipe signal at the end of the service socket send process can receive a signal sigpipe.	  */void Signal_pipe (int signo) {Pthread_kill (read_id,sigquit);//Send Sigquit Pthread_join (read_id,null) to the read thread;
	
	Blocks the thread from running until the read thread exits.                Close (CONNFD);
	
	Close connection printf ("read pthread out \ n");              Pthread_exit (0); End Write Thread}/* Read thread received sigquit signal, execution thread exit operation/void Pthread_out (inT signo) {pthread_exit (0);}
	/* Read thread execution function */void* Read_func (void* Arg) {char readbuff[maxline];
	int n = 0;

	int FD;    FD = * (int*) arg;

	/*main The main process passes the connection file descriptor/memset (&readbuff,0,sizeof (Readbuff)); Signal (sigquit,pthread_out);  /* Registered Sigquit signal */while (1) {n = recv (fd, Readbuff, maxline, 0);
		/*RECV here is blocking run/if (n > 0) {printf ("Server recv data:%s \ n", Readbuff);
}
	};
	}/* Write thread execution function/void* write_func (void* Arg) {char writebuff[maxline];
	char* write = "I am Server";
	unsigned char i = 0;
	int num = 0;

	int FD;
	FD = * (int*) arg;
	
	memset (&writebuff,0,sizeof (Writebuff)); Signal (SIGPIPE,SIGNAL_PIPE);
		/* Registered SIGPIPE signal * * while (1) {sleep (1);
	Send (Fd,write,strlen (write) +1,0);/* Sending data to client/} int main (int argc, char** argv) {char buff[maxline];
	int num;
	int Addrlen;  struct sockaddr_in server_addr;  /* Server address structure * * struct sockaddr_in client_addr;
/* Client Address structure * * (LISTENFD = socket (af_inet,sock_stream,0) = = 1)/* Create a streaming socket/{		printf ("Create Socket Error:%s (errno:%d) \ n", Strerror (errno), errno);
	Exit (0);
	/* Set the service-side address * * Addrlen = sizeof (struct sockaddr_in);
	memset (&server_addr, 0, Addrlen);    server_addr.sin_family = af_inet; /*af_inet said the IPV4 intern Agreement * * server_addr.sin_addr.s_addr = htonl (Inaddr_any); /*inaddr_any can monitor any IP/server_addr.sin_port = htons (port);
		/* Set port/* binding address structure to socket descriptor */if (Bind (LISTENFD, (struct sockaddr*) &server_addr, sizeof (SERVER_ADDR)) = = 1) {
		printf ("Bind socket Error:%s (errno:%d) \ n", Strerror (errno), errno);
	Exit (0); /* Set the listener queue, which is set to 1, which means that only one client can be processed at the same time/if (Listen (LISTENFD, 1) = = 1) {printf ("Listen socket Error:%s (errno:%d) \ n",
		Strerror (errno), errno);
	Exit (0); } signal (Sigint,stop);
		/* Registered SIGINT signal * * while (1) {printf ("Wait client accpt \ n");
			if ((CONNFD = Accept (LISTENFD, (struct sockaddr*) &client_addr, &addrlen)) = = 1)/* Receive client connection, this will block until there is a client connection * * printf ("Accept socket Error:%s (errno:%d)", Strerror (errno), errno);
			Continue } if (Pthread_create (&AMP;READ_ID,NULL,READ_FUNC,&AMP;CONNFD))/* Create a read thread */{printf ("Pthread_create read_func er
		r\n ");  } if (Pthread_create (&AMP;WRITE_ID,NULL,WRITE_FUNC,&AMP;CONNFD))/* Create write Thread */{printf ("Pthread_create write_func
		Err\n "); } pthread_join (Write_id,null);
	/* Blocking until the write process exits to make a new client connection/printf ("Write pthread out \ n");


 }
}
There is a need to pay special attention to the collection of thread resources, because each time a connection is made to the client, the server creates a thread, so we need to reclaim the thread resource when the client disconnects. There are two ways to detect whether a client has been disconnected. First: The above SERVER.C server uses, when the client disconnects, send the process will receive a sigpipe signal, the server received Sigpipe signal on the thread exit operation. Second: The recv function is disconnected at the other side and it returns parameter 0, which can also be used to know that the client has disconnected from the connection. This is the way you use the CLIENT.C Client test program below.

Here's another question, the signal (sigpipe,signal_pipe) function is registered, I would have placed it in the main thread main function, and then the read and write threads were recycled at signal_pipe, resulting in the read process being recycled properly, Write thread has failed to recycle, the specific reason is not clear, for expert advice. So I just use the sigquit signal, when the write thread receives the SIGPIPE signal, notifies the read thread to quit until it exits and then exits the write thread. This enables the recovery of system resources.

Client Clients Test Program:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/ types.h> #include <sys/socket.h> #include <netinet/in.h> #include <termios.h> #include <sys/ types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h&gt
;
#include <signal.h> #define MAXLINE 256 #define PORT 6666 int fd;
	/* Linux CTRL + C generates SIGINT signals to receive SIGINT signals into the function/void stop (int signo) {printf ("Client stop\n");  
	Close (FD);
_exit (0);
	/* Client processing function/void client_process (void) {char readbuff[maxline];
	Char Writebuff[maxline];
	char * write = "I am Client";
	
	int num = 0; while (1) {num = recv (fd,readbuff,maxline,0);//Receive server data, Recv here if no data will block */if (num > 0) {printf ("client Read
			Data:%s \ n ", Readbuff); Send (FD, write, strlen (write) +1, 0); * * Receive data and then send a string to the server (num = 0)/*recv return value of 0 indicates that the server has disconnected the connection/{stop (1); * Execute exit operation/}}

int main (int argc, char** argv) {struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;

	int ret;
	FD = socket (af_inet,sock_stream,0);/* Create a streaming socket/if (FD < 0) {printf ("clinet socket err \ n");
	/* Set the service-side address/memset (&server_addr,0,sizeof (SERVER_ADDR)); 				server_addr.sin_family = af_inet; /*af_inet that the IPV4 intern protocol * * server_addr.sin_addr.s_addr = htonl (inaddr_any);/*inaddr_any can monitor any IP/server_addr.sin_p				ORT = htons (PORT); /* Set Port */Inet_pton (AF_INET,ARGV[1],&AMP;SERVER_ADDR.SIN_ADDR);/* Convert the String type IP address entered by the user into an integer/connect (FD, struct	sockaddr*) &server_addr,sizeof (SERVER_ADDR));/* Connect Server * * Signal (SIGINT,STOP);		/* Registered SIGINT Signal * * client_process ();
/* Enter the processing function */close (FD);/* Closing file/return 0;



 }
The client is using the return value of the RECV function to determine whether the server is disconnected instead of the sigpipe signal, mainly in this program, my implementation is that the Send function sends the data to the server, so if the sigpipe signal is not triggered here. If you want to implement the client's independent transceiver, you can imitate the implementation of the service side, this is no longer realistic.

Here is the test execution:

root@ubuntu:/home/share/socket#./server Wait Client ACCPT server recv data:i AM Client server recv data:i AM Client Server recv data:i AM Client server recv data:i AM Client server recv data:i AM Client server recv data:i am Clien T Server recv data:i AM Client server recv data:i am client read pthread out write pthread out wait client accpt s Erver recv data:i AM Client server recv data:i AM Client server recv data:i am client read pthread out write Pthrea  D out wait client accpt root@ubuntu:/home/share/socket#/client 127.0.0.1 Client read DATA:I AM Server client Read DATA:I am Server Client read DATA:I AM Server client read DATA:I AM Server client read DATA:I AM server Clien T read DATA:I am Server client read DATA:I AM Server client read DATA:I AM server ^cclient Stop Root@ubuntu:/home /share/socket#./client 127.0.0.1 Client read DATA:I AM Server client read DATA:I AM Server client read DATA:I am Server ^cclient Stop ROot@ubuntu:/home/share/socket#  
Executing the server from the program waiting for the client connection, executing the client program to establish a connection with the server, the server sends a string to the client every second: I am server, the client sends a string to the server after receiving the data: I am client. When the client side presses CTRL + C to end the client program, the server detects that the clients are disconnected, closes the file descriptor, and reclaims the created read and write threads.

root@ubuntu:/home/share/socket#./server wait 
client accpt 
server recv data:i AM Client 
server recv data:i A M client 
server recv data:i AM Client 
server recv data:i AM Client 
server recv data:i am client 
^cstop< c7/>root@ubuntu:/home/share/socket# 

root@ubuntu:/home/share/socket#./client 127.0.0.1
Client Read data:i AM Server 
Client read DATA:I AM server 
client read DATA:I AM server 
client read DATA:I am server
  
   client read DATA:I AM server 
client Stop
root@ubuntu:/home/share/socket#
  
In the service side press the CTLC + C server to detect the SIGINT signal, close the file descriptor end program, the entire process exits. The client detects that the server is disconnected and performs an exit operation.

This is what happens when only one client connects at the same time, and if you want to handle multiple client connections at the same time, it does not seem appropriate to use this approach and can be handled in a multiple-process manner.







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.