Summary of Network programming (I.)

Source: Internet
Author: User
Tags bind error handling socket socket error htons

These days in the Muduo network library, by the way the second detailed reading of "UNIX network programming."
Start with the most basic programming model, documenting the process of improving the program and the finely grained knowledge points.
First look at the library functions necessary to start a server program.
  
Socket

#include <sys/socket.h>
int socket (int family,int type,int protocol);
The family parameter specifies the protocol family, Af_inet (IPv4), af_inet (IPv6), and so on. The type parameter indicates the socket type, TCP is a byte stream protocol, and only Sock_stream is supported. The protocol parameter indicates the transport protocol, and there are three classes of TCP,UDP,SCTP. There is usually no difference between af_xxx and pf_xxx. Connect
#include <sys/socket.h>
int connect (int sockfd,const struct sockaddr *servaddr, socklen_t addrlen);
                        Return: If 0 is returned successfully, the error returns-1
SOCKFD is the socket descriptor returned by the socket function, and the second parameter is a pointer to the socket address structure, and three is the structure size. The TCP three handshake is fired in the Connect function. Why TCP requires three handshake. Instead of two or more, first because theoretically, three times is to ensure a reliable basic number of times, not to guarantee the number of reliable. Second, it can prevent invalid message request connection, such as a request for a message because the network delay has been stranded, wait until the connection is released before the server, the server will be confirmed, the client does not respond, the server will always block waiting for the client data, The resources of the server are wasted. There are several cases where a function error is returned, which is generally divided into a timeout, in which case there is a retransmission mechanism; the server responds to RST, there are no processes on the specified port to wait for the connection; Destination unreachable on the router. Bind
#include <sys/socket.h>
int bind (int sockfd,const struct sockaddr *myaddr,socklen_t addrlen);
There are two main uses, one is when the server starts to bind a port that is released to everyone. The second is to bind a specific IP address to its socket. Bind can specify IP and port numbers, and can not specify。 For IPV4, the constant value Inaddr_any is a wildcard address, typically 0, and the kernel chooses the IP. Listen
#include <sys/socket.h>
int listen (int sockfd,int backlog);
function should be called after the socket and bind, in fact, just beginning to learn the classmate may not understand bind, connect and listen, bind is to implement the socket and protocol family bundle, and listen is responsible for passive listening to the socket connection, is from the server side of the PassiveBehavior, connect is part of the client ActiveInitiate the Act. SOCKFD is the socket that is being listened to, the backlog specifies the queue MaximumThe number of connections, the listener sockets generally have two queues. The connection queue is not completed, that is, three handshake has not been successful connection, the completed queue is already shook hands, in the connection state. Accept
#include <sys/socket.h>
int accept (int sockfd,struct sockaddr *cliaddr, socklen_t *addrlen);
                    Returned: Successfully returned non-negative descriptor, error 1
Just now the Listen function mentions two queues, the connection is not complete and the connection queue is completed, and the accept is to return a connection from the team header that has completed the connection queue, and when the queue is empty, the process sleeps. Pay attention to ... , there are two descriptors, one is the listener descriptor as the first parameter, and the other is the new one generated by the kernel as the return value. A server typically creates only one listener socket, which is always present during its declaration period. The kernel then creates a connected socket for each customer, completes the service, and closes the socket.

Here is a small example of the return server time, my code is running on the cloud9 platform, a very good online integration environment, I chose the C + + programming environment. It will automatically generate a makefile file, the simple definition of makefile is to help you complete the compilation of the script file, you can also choose one at the command line to enter the compilation command. The document is broadly as follows:
  

All:hello-cpp-world hello-c-world

%:%.cc
    g++-std=c++11 $<-o $@

%:%.c
    gcc $<-o $@

The following is the server code, the approximate process is the same as the beginning of the picture process:

#include <iostream> #include "unp.h" void errorhandling (const char *message);
    Error handling int main () {int listnenfd,connfd;
    struct sockaddr_in servaddr;
    The buffer used to store the time string char buff[maxline];
    Test the client to return data with a buffer of char readbuf[maxline];
    time_t ticks;

    Establish socket LISTNENFD = socket (pf_inet,sock_stream,0);
    A function bzero (&servaddr, sizeof (SERVADDR)) that is initialized in place of memset;
    Set protocol family//ipv4 servaddr.sin_family = af_inet;
    Here is a htonl function, which converts the host host byte order into network byte order servaddr.sin_addr.s_addr = htonl (Inaddr_any);
    The listening port Servaddr.sin_port = htons (8081);
    Bind port if ( -1== bind (LISTNENFD, (sa*) &servaddr, sizeof (SERVADDR))) errorhandling ("Socket_error");

    Start monitoring if ( -1==listen (Listnenfd,listenq)) errorhandling ("Listen () error");
    std::cout<< "Now listen" <<std::endl; Now the server belongs to an iterative server, only one connection can be served at a time, which is of course not very efficient for (;;)
        {CONNFD = Accept (LISTNENFD, (sa*) null, NULL); Read (Connfd,readBuf,sizeof (READBUF)-1);
        printf ("%s", readbuf);
        Gets the time to write the buffer after the send out ticks = times (NULL);
        snprintf (buff, sizeof), "%.24s\r\n", CTime (&ticks));

        Later can use sendmsg and so on instead of write (CONNFD, buff, strlen (buff));
    Close (CONNFD);
} std::cout<< "Test" <<std::endl;}
    void errorhandling (const char *message) {fputs (message, stderr);
    FPUTC (' \ n ', stderr);
Exit (1); }

The header file to use

#ifndef _unp_h
#define _UNP_H
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <error.h>
#define SA struct SOCKADDR

#define MAXLINE 1024x768
#define LISTENQ
#define CPU_VENDOR_OS "Linux"

#endif

Run in the background after compiling

g++ server.cc-o server
./server &

Client program:

 #include "unp.h" #include "myerr.h" int main (int argc,char** argv) {int sockfd,n;
    Char recvline[maxline+1];

    struct sockaddr_in servaddr;

    if (argc! = 2) err_quit ("usage:a.out<ipaddress>");

    if (SOCKFD = socket (af_inet, sock_stream, 0)) < 0) Err_sys ("Socket error");
    Bzero (&servaddr, sizeof (SERVADDR));
    servaddr.sin_family = af_inet;
    Servaddr.sin_port = htons (8081); Here the client takes parameters, the following function converts the string into binary results stored in SIN_ADDR if (Inet_pton (Af_inet, argv[1], &servaddr.sin_addr) <= 0) err_q

    Uit ("Inet_pton error for%s", argv[1]);
    if (Connect (SOCKFD, (SA *) &servaddr, sizeof (SERVADDR)) <0) Err_sys ("Connect error");
        Reads the bytes sent to the server after output to the standard output while ((n = Read (SOCKFD, Recvline, MAXLINE)) >0) {Recvline[n] = 0;
    if (fputs (recvline, stdout) = = EOF) Err_sys ("fputs error");

    } if (n < 0) Err_sys ("read error");
Exit (0); }

Compiling and running the program

g++ daytimetcpcli.cc-o client
./client 127.0.0.1
Result:
Tue APR  5 13:54:12 2016

Here are a few common directives:

Show all network port information
Netstat-na
//Provide network interface information
Netstat-ni
//With interface name, get interface details
ifconfig eth0
// Locate many hosts on the local network, ping Ping-b through the broadcast address shown above
XXX.XXX.XXX.XXX

The above server is iterative, how to implement a concurrent server, can provide multiple connections at the same time service. The simplest model is a block-type fork+exec. Fork
  

#include <unistd.h>
pid_t fork (void);
                    Returns: 0 in child process, child process ID in parent process
This function calls One timeReturn Two plays, the parent process is returned once in the calling process, the ID number of the child process is returned, and returned once in the child process, with a return value of 0. The parent process transfers the controller to the operating system, and the operating system replicates an almost identical process to complete the operation.

Because of this, the parent-child process shares many things, such as the descriptor that is opened by all the parent processes. Typically, the parent process calls accept after fork, and then the child process then reads and writes the socket, and the parent process closes the socket.

The following is a simple outline of a concurrent server:

pid_t pid;
int listenfd,connfd;
LISTENFD = socket (...);
Bind (LISTENFD,...);
Listen (Listenfd,listenq);
Why not use while (1) presumably to omit a decision, but the compiler may have optimized the for
(;;) {
    CONNFD = accept (listenfd,...);
    if (PID = fork ()) = = 0) {
        close (LISTENFD);
        Doit (CONNFD);
        Close (CONNFD);
        Exit (0);
    }
    Close (CONNFD);
}

Here is a small detail, why close in the parent process does not directly terminate the connection with the client. Because each file and socket has a reference count, the concept and the reference count in the smart pointer are similar, the count value is 0 to actually close the descriptor, and of course there is a way to send a TCP fin section, shutdown function.

Looking forward to the next improvement.

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.