Summary of TCP communication problems in Linux-general Linux technology-Linux programming and kernel information. The following is a detailed description. Here, we will summarize several issues that need to be paid attention to when using TCP communication in linux, all of which were problems encountered during previous work.
Problem 1. Incomplete questions about sending and receiving data
Taking receiving as an example, when the peer sends 1000 bytes of data, the local end receives the data, if you call recv to return 500 and errno = EAGAIN, this error indicates that the current device is busy. Try again later. The idealized solution is as follows:
With the select or epoll mechanism, when data arrives, select or epoll will be notified. At this time, it will be received until the recv returns 0, indicating that all data is received. In the process, when errno = EAGAIN, the received data is paused and cached. When the device is readable again, select or epoll will notify you again and continue receiving the cached data until the value of recv is 0.
However, this method requires caching some received data, which is very cumbersome. I have implemented the following simple implementation: part of the code in my encapsulated epoll:
CODE: int Mo_epoll_recv (int s, void * buf, int buf_size, int err) { Int recved_len = 0; Int total_recv_len = 0; Int count = 0; If (buf = NULL | buf_size <= 0) { Return-1; } MO_DEBUG ("to recv some data! \ N "); Do { // MO_DEBUG ("call recv, total_recv_len = % d recv_len = % d \ n", total_recv_len, buf_size-total_recv_len ); Recved_len = recv (s, buf + total_recv_len, buf_size-total_recv_len, err ); // MO_DEBUG ("called recv, recved_len = % d \ n, errno = % d: EAGAIN = % d: % s \ n", recved_len, errno, EAGAIN, strerror (errno )); If (recved_len <0 & errno! = EAGAIN) { MO_ERROR ("some error when recv erron: % d, % s", errno, strerror (errno )); Break; } Else if (recved_len <0 & errno = EAGAIN) { Recved_len = 1; /* 10 s timeout */ If (++ count> 200) { Break; } Usleep (1000*50 ); Continue; } Total_recv_len + = recved_len; If (total_recv_len> = buf_size) { Recved_len = 0; // MO_DEBUG ("recv % d bytes !!!!! ", Total_recv_len ); Break; } Usleep (1000*50 ); } While (recved_len> 0 ); MO_DEBUG ("recv some data over % d bytes! \ N ", total_recv_len ); If (recved_len =-1) Return-1; Return total_recv_len; } Int Mo_epoll_send (int s, const void * buf, int buf_size, int err) { Int sended_len = 0; Int total_send_len = 0; If (buf = NULL | buf_size <= 0) { Return-1; } MO_DEBUG ("to send some data! \ N "); Do { Sended_len = send (s, (buf + total_send_len), buf_size-total_send_len, err ); If (sended_len =-1 & errno! = EAGAIN) { Break; } Else if (sended_len =-1 & errno = EAGAIN) { Sended_len = 1; Continue; } Total_send_len + = sended_len; If (total_send_len> = buf_size) { Sended_len = 0; // MO_DEBUG ("send % d bytes !!!!! ", Total_send_len ); Break; } } While (sended_len> 0 ); MO_DEBUG ("send some data over % d bytes! \ N ", total_send_len ); If (sended_len =-1) Return-1; Return total_send_len; } |