1. Preface
Many friends in the development of network programming may have encountered such a problem, in the process of receiving binary stream data, using the Strlen library function to get
The binary data length is not accurate. Why?? First, the strlen is used for the statistical length of the string, not the binary stream data, so the
Getting the binary data stream is not appropriate for the fixed length. The problem solved must be judged by using the return value of the network receive function, such as recv and Recvfrom.
2. Simple Web server
Simple Web server in Linux is easy to do, it is just the following steps
Create a network socket (socket)--bind the ground socket to the network (BIND)--Set the maximum number of listeners (listen)--Listen for client access (accept)
3. Specific examples
(Service side)
1#include <stdio.h>2#include <string.h>3#include <errno.h>4#include <sys/types.h>5#include <sys/socket.h>6#include <arpa/inet.h>7#include <unistd.h>8 9 #defineWeb_port 8080Ten #defineMax_client 5 One #defineMAX_RECV 1024 A - intMainintargcChar*argv[]) - { the //1. Create a network socket - intSock = socket (Af_inet,sock_stream,0); - if(0>sock) - { +fprintf (stderr,"Socket:%s\n", Strerror (errno)); - return-1; + } A at //2. Set the port to be released immediately, can be used immediately - intOn =1; -SetSockOpt (Sock,sol_socket,so_reuseaddr,&on,sizeof(on)); - - //3. Bind the ground socket to the network - structsockaddr_in localaddr; insocklen_t Localaddrlen =sizeof(LOCALADDR); - tolocaladdr.sin_family =af_inet; +Localaddr.sin_port =htons (web_port); -LOCALADDR.SIN_ADDR.S_ADDR =htonl (inaddr_any); the * if(0> Bind (Sock, (structSOCKADDR *) &Localaddr,localaddrlen)) $ {Panax Notoginsengfprintf (stderr,"bind:%s\n", Strerror (errno)); - return-1; the } + A //4. Set the maximum number of listeners the if(0>Listen (sock,max_client)) + { -fprintf (stderr,"bind:%s\n", Strerror (errno)); $ return-1; $ } - - //5. Listening for client access the structsockaddr_in peeraddr; -socklen_t Peeraddrlen =sizeof(PEERADDR);Wuyi CharCRECVDATABUF[MAX_RECV] = {0}; thessize_t Srecvret =0; - Wu while(1) - { About intCONNFD = Accept (sock, (structSOCKADDR *) &peerAddr,&Peeraddrlen); $ if(0>connfd) - { -fprintf (stderr,"Accept:%s\n", Strerror (errno)); - return-1; A } + thememset (Crecvdatabuf,0,sizeof(CRECVDATABUF)); -Srecvret = recv (Connfd,crecvdatabuf,sizeof(CRECVDATABUF),0); $ if(0>Srecvret) the { thefprintf (stderr,"recv:%s\n", Strerror (errno)); the return-1; the } - inprintf"\n**************************************\n"); theprintf"Srecvret =%ld\n", Srecvret); theprintf"strlen (crecvdatabuf) =%lu\n", strlen (CRECVDATABUF)); Aboutprintf"**************************************\n"); the theprintf"\ncrecvdatabuf: \n%s\n\n", crecvdatabuf); the + Close (CONNFD); - } the Bayi Close (sock); the the return 0; -}
Client
#include <stdio.h>#include<string.h>#include<errno.h>#include<sys/types.h>#include<sys/socket.h>#include<arpa/inet.h>#include<stdlib.h>#include<unistd.h>#defineWeb_port 8080intMainintargcChar*argv[]) { //1. Create a network socket intSock = socket (Af_inet,sock_stream,0); if(0>sock) {fprintf (stderr,"Socket:%s\n", Strerror (errno)); return-1; } //2. Set the port to be released immediately, can be used immediately intOn =1; SetSockOpt (SOCK,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); //3. Set the server's address and link send binary stream data structsockaddr_in serveraddr; socklen_t Serveraddrlen=sizeof(SERVERADDR); Serveraddr.sin_family=af_inet; Serveraddr.sin_port=htons (Web_port); ServerAddr.sin_addr.s_addr=htonl (Inaddr_any); if(0= = Connect (sock, (structSOCKADDR *) &Serveraddr,serveraddrlen)) {FILE*pfile = fopen ("./linux.bin.ub","RB"); if(NULL! =pFile) { //4. Get the data size of a binary fileFseek (PFile,0, Seek_end); LongLfilesize =Ftell (PFile); Rewind (PFile); //5. Read the data and send Char*psendbuf = (Char*)malloc(lfilesize+1); if(NULL = =psendbuf) {fprintf (stderr,"malloc:%s\n", Strerror (errno)); return-1; } memset (Psendbuf,0, lfilesize+1); Fread (Psendbuf,lfilesize,1, PFile); Fclose (PFile); Send (Sock,psendbuf,lfilesize,0); Free(PSENDBUF); Close (sock); } } return 0;}
(Binary stream data: 9.27 MB (9,728,804 bytes))
4. Comparison results:
First I on the server side just accept the data, the maximum length of 1024 bytes, then how to receive the degree of binary data should actually be 1024 bytes (assuming that the network is normal, only received once, because the file's binary stream data size is 9728804 bytes, So the received data length is 1024 bytes), the specific results are as follows:
5. Conclusion:
As you can see from the result graph, if you use strlen to get the data, only 12 bytes are used, and if you use the return value to set the length, it does 1024 bytes, and the return value is correct. Because
This, in the network programming, recommended that everyone in the sending binary file stream or in receiving binary file stream, remember not to use strlen for fixed length, or error prone . But it's not a problem if you're sending data from a string stream, but for system security and data accuracy, using a return value is better than strlen.
Potential.
Those things in the Linux network that receive the "binary" stream---The recv return value and the Strlen Library function dialog