Linux Network programming socket implementation of simple client and server communication (based on TCP) __ block chain

Source: Internet
Author: User
Tags error code socket error strcmp htons
first, introduce the common API of network programming through socket based on TCP protocol 1, if the reader is not very familiar with, you can first read a few blog before I wrote, there are sockets, address structure of understanding, more convenient for readers to understand

Addresses are: 1, http://blog.csdn.net/u011068702/article/details/56479927 2), http://blog.csdn.net/ u011068702/article/details/56481754 3), http://blog.csdn.net/u011068702/article/details/56483784 4), http://blog.csdn.net/u011068702/article/details/56495562


2. Introduction to Socket (TCP) programming API 1), socket

int socket (int family, int type, int protocol);

Socket () to open a network communication port, if successful, like Open () return a file descriptor, the application can be like read and write files with Read/write on the network to send and receive data, if the socket () call error return 1. Specified as af_inet for the ipv4,family parameter. For the TCP protocol, the type parameter is specified as Sock_stream, which represents a stream-oriented transport protocol. In the case of a UDP protocol, the type parameter specifies Sock_dgram, which represents a datagram-oriented transport protocol. An introduction to the protocol parameter Conlio, specified as 0.

int bind (int sockfd, const struct SOCKADDR *myaddr, socklen_t Addrlen);


The network address and port number that the server program listens to are usually fixed. When the client program learns the server program's address and port number, it can initiate a connection to the server, so the server needs to invoke bind to bind a fixed network address and port number, bind () successfully return 0, and failure returns-1. The role of BIND () is to bind the parameter sockfd and myaddr together so that the SOCKFD file descriptor for network traffic
Listen for the address and port number described by the myaddr. As I said before, struct sockaddr * is a generic pointer type, MYADDR parameter
Number can actually accept the SOCKADDR structure of multiple protocols, and they vary in length, so a third argument is required
Addrlen Specifies the length of the struct body. The MYADDR parameter in our program is initialized like this:

Bzero (&servaddr, sizeof (SERVADDR));
servaddr.sin_family = af_inet;
SERVADDR.SIN_ADDR.S_ADDR = htonl (inaddr_any);
Servaddr.sin_port = htons (Serv_port);

First the entire structure is zero, then set the address type is af_inet, the network address is Inaddr_any, this macro represents any local IP address, because the server may have more than one network card, each network card may also bind multiple IP addresses, so that the settings can be monitored on all IP addresses, Until you establish a connection with a client to determine exactly which IP address to use, the port number is Serv_port, we define 1234.


2), listen

int listen (int sockfd, int backlog);


A typical server program can serve multiple clients at the same time, when a client initiates a connection, the server calls accept () returns and accepts the connection, and if a large number of clients initiate the connection and the server is too late to process, the accept client is in the connection waiting state, listen () Declares that the SOCKFD is in a listening state and that a maximum of backlog clients are allowed to be in the receiving State, if more connection requests are received, they are ignored. Listen () successfully returned 0, failure returned-1.


3), accept

int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

After the three-party handshake is complete, the server calls accept () to accept the connection and, if the server calls accept () without a client connection request, blocks the wait until a client is connected. CLIADDR is an outgoing parameter that accept () the address and port number of the outgoing client when it returns. The Addrlen parameter is an incoming outgoing parameter (Value-result argument) that is passed the length of the buffer cliaddr provided by the caller to avoid a buffer overflow problem, which is the actual length of the client address structure (which may not be filled with the buffer area provided by the caller). If the CLIADDR parameter is passed NULL, it indicates that the client's address is not cared for.
The structure of our server program is this:
while (1) {
Cliaddr_len = sizeof (CLIADDR);
CONNFD = Accept (LISTENFD, (struct sockaddr *) &cliaddr, &cliaddr_len);
n = Read (CONNFD, buf, maxline);
......
Close (CONNFD);
}


The whole is a while dead loop that handles one client connection at a time. Because Cliaddr_len is an incoming outgoing parameter, the initial value should be assigned before each call to accept (). The parameter listenfd of accept () is the previous listener file descriptor, and the return value of accept () is another file descriptor CONNFD, which then communicates with the client through this CONNFD, and finally closes the CONNFD disconnect without closing LISTENFD and return to the beginning of the loop again LISTENFD is still used as a accept parameter. Accept () successfully returned a file descriptor with an error returning-1. Because the client does not need a fixed port number, you do not have to call bind (), and the client's port number is automatically allocated by the kernel. Note that the client is not not allowed to call bind (), but there is no need to call bind () to fix a port number, nor does the server have to call bind (), but if the server does not call bind (), the kernel automatically assigns listening ports to the server, and the port number is different each time Clients will have trouble connecting to the server. 4), connect

int connect (int sockfd, const struct SOCKADDR *servaddr, socklen_t Addrlen);


The client needs to call Connect () connection server, connect and bind parameters in the same form, the difference is that the parameters of bind is their own address, and connect parameters are the other side of the address. Connect () successfully returned 0, error return-1. 5), write function

    ssize_t write (int fd,const void *buf,size_t nbytes);


The Write function writes the nbytes byte content in buf to the file descriptor, returns the number of bytes written successfully, and returns 1. and sets the errno variable. In a Web program, there are two possibilities when we describe the comfortable writing of data to a socket file:

1. The return value of write is greater than 0, which means that some or all of the data is written, so that the data is written in a while loop, but the BUF and nbytes parameters in the loop are updated by ourselves, that is to say, Writing functions in network programming is not responsible for all the data after the completion of the return, perhaps halfway back.

2, the return value is less than 0, this time error, you need to according to the type of error to deal with the corresponding.

If the error is eintr, there is an interrupt error at the time of writing, if the epipe indicates that there is a problem with the network connection.


6), read function

    ssize_t Read (int fd,void *buf,size_t nbyte)

The read function is responsible for reading content from FD, and when read succeeds, read returns the number of bytes actually read, and if the return value is 0, it indicates that the end of the file has been read and less than 0 indicates a read error.

If the error is eintr, there is an interrupt error at the time of writing, if the epipe indicates that there is a problem with the network connection.

7), recv function and send function


The RECV function and the read function provide the same functionality as the read and write functions, with the difference that they provide four parameters.

    int recv (int fd,void *buf,int len,int flags)

    int send (int fd,void *buf,int len,int flags)


The previous three arguments are the same as the read and write functions. The fourth parameter can be 0 or a combination:

Msg_dontroute: Do not lookup table

is a flag used by the Send function, which tells the IP that the destination host does not have the necessary lookup table on the local network, which is commonly used in network diagnostics and routing programs.

Msg_oob: Accept or take out Out-of-band data

Indicates that Out-of-band data can be received and sent.

Msg_peek: View data, do not remove data from system buffers

Is the flag used by the RECV function to read content only from the system buffer, without knowing the contents of the system buffer. This will still be the same content the next time you read it, usually using this flag when you have a process reading and writing data.

Msg_waitall: Waiting for all data

Is the use flag of the RECV function, which means that when all the information arrives, the recv return blocks until the specified condition is met or an error occurs.
8), close is defined as follows:

#include <unistd.h>

int close (int fd);

Turn off read and write.

Success returns 0, error returns-1, error code ERRNO:EBADF indicates that FD is not a valid descriptor; Eintr indicates that the close function was interrupted by a signal; Eio represents an IO error.



2, client and service-side communication map




3, the implementation of the current simple client and server communication (based on TCP)

This is realized is the client writes the data, the service side reads, then writes reads the data to the client to display 1, the service side socket1.c code as follows

#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include < netdb.h> #include <errno.h> #define PORT 2345 #define MAXSIZE 1024 int main (int argc, char *argv[]) {int S
    OCKFD, NEWSOCKFD;
    Define the service end socket interface data structure struct SOCKADDR_IN server_addr;
    struct sockaddr_in client_addr;
    int sin_zise, portnumber;
    Send data buffer char buf[maxsize];
    Defines the client socket interface data structure int addr_len = sizeof (struct sockaddr_in);
	if ((SOCKFD = socket (af_inet, sock_stream, 0)) < 0) {fprintf (stderr, "create socket failed\n");
    Exit (Exit_failure);
    } puts ("Create socket Success");
    printf ("SOCKFD is%d\n", SOCKFD);
    Empty the structural variables representing the address bzero (&server_addr, sizeof (struct sockaddr_in));
    Set the addr member variable information server_addr.sin_family = af_inet;
    Server_addr.sin_port = htons (port);
    Set IP to native IPSERVER_ADDR.SIN_ADDR.S_ADDR = htonl (Inaddr_any); if (bind (SOCKFD, struct sockaddr*) (&server_addr), sizeof (struct sockaddr)) < 0) {fprintf (stderr, "bin
	D failed \ n ");
    Exit (Exit_failure);
    } puts ("Bind success\n");
	if (Listen (SOCKFD) < 0) {perror ("Listen fail\n");
    Exit (Exit_failure);
    } puts ("Listen success\n");
    int sin_size = sizeof (struct sockaddr_in);
    printf ("Sin_size is%d\n", sin_size); if ((NEWSOCKFD = Accept (SOCKFD, (struct sockaddr *) (&AMP;CLIENT_ADDR), &sin_size)) < 0) {perror ("Accep
        T error ");
    Exit (Exit_failure);
    printf ("accepted a new connetction\n");
    printf ("New socket ID is%d\n", NEWSOCKFD);
    printf ("Accept clent IP is%s\n", Inet_ntoa (CLIENT_ADDR.SIN_ADDR));
    printf ("Connect Successful Please input message\n");
    Char sendbuf[1024];
    Char mybuf[1024];
         while (1) {int len = recv (NEWSOCKFD, buf, sizeof (BUF), 0); if (strcmp(BUF, "exit\n") = = 0) break;
          Fputs (buf, stdout);
          Send (NEWSOCKFD, buf, Len, 0);
	  memset (sendbuf, 0, sizeof (SENDBUF));
    memset (buf, 0, sizeof (BUF)); 
    Close (NEWSOCKFD);
    Close (SOCKFD);
    Puts ("Exit success");
    Exit (exit_success);
return 0;
 }

2, the client socket3.c code as follows

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include < sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <string.h> #include <errno.h

> #define PORT 2345 int count = 1;
   int main () {int sockfd;
   Char buffer[2014];
   struct sockaddr_in server_addr;
   struct Hostent *host;
   int nbytes; 
      if ((SOCKFD = socket (af_inet, sock_stream, 0)) = = 1) {fprintf (stderr, "socket Error is%s\n", Strerror (errno));
   Exit (Exit_failure);
   } bzero (&server_addr, sizeof (SERVER_ADDR));
   server_addr.sin_family = af_inet;
   Server_addr.sin_port = htons (port);
   SERVER_ADDR.SIN_ADDR.S_ADDR = htonl (Inaddr_any); The client issues a request if (connect (SOCKFD, struct sockaddr *) (&AMP;SERVER_ADDR), sizeof (struct sockaddr)) = = 1) {Fpri
      NTF (stderr, "Connect failed\n");
   Exit (Exit_failure);
   } Char sendbuf[1024];
   Char recvbuf[2014]; while (1) {fgets (sendbuF, sizeof (SENDBUF), stdin);
   Send (SOCKFD, SendBuf, strlen (SENDBUF), 0);
      if (strcmp (SendBuf, "exit\n") = = 0) break;
      Recv (SOCKFD, Recvbuf, sizeof (RECVBUF), 0);
      Fputs (Recvbuf, stdout);
      memset (sendbuf, 0, sizeof (SENDBUF));
   memset (recvbuf, 0, sizeof (RECVBUF));
   Close (SOCKFD);
   Exit (exit_success);
return 0;
 }



4. Operation Result


5, Summary

Service end: Socekt-> bind-> listen->accept

Client: Socket->connect

TCP is connection-oriented, secure, without duplication, and in ordered order.


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.