Network programming -- C/S model

Posted by The-Master on Thu, 20 Jan 2022 04:15:00 +0100

catalogue

TCP introduction

C/S model framework

Server side

1. Create socket

2. Bind IP address and port number

3. Use this socket to listen for connection requests

4. When the request arrives, call the accept function to copy the socket and process the request

5. Data communication

client side

        1. Create socket

        2. Use the created socket to send a connection request to the server

        3. Data communication using socket

server side simple example code

client side simple example code

Existing problems

TCP introduction

TCP: transmission control protocol, which provides connection oriented, one-to-one reliable data transmission protocol.

TCP features: it can provide high reliability communication (i.e. communication without data error, data loss, data out of order and data repeated arrival).

TCP application:

  1. It is suitable for communication with high requirements for transmission quality and transmitting a large amount of data.
  2. When reliable data transmission is needed, TCP protocol is usually applied.
  3. The functions related to user login account management of instant messaging software such as MSN/QQ usually use TCP protocol.

C/S model framework

Server side

1. Create socket

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

This socket is used later to listen for client requests.

2. Bind IP address and port number

         int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

When filling in the addr parameter of this function, please note that we first fill in struct sockaddr_in. When passing parameters, sockaddr_ A pointer of type in is strongly converted to a pointer of type sockaddr.

Note: switching between network byte order and local byte order.

Port:

        uint32_t htonl(uint32_t hostlong);

       uint16_t htons(uint16_t hostshort);

       uint32_t ntohl(uint32_t netlong);

       uint16_t ntohs(uint16_t netshort);

ip address:

        in_addr_t inet_addr(const char *cp);

        int inet_pton(int af, const char *src, void *dst);

        const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);

3. Use this socket to listen for connection requests

        int listen(int sockfd, int backlog);

The socket created by socket is an active socket, that is, a socket that actively connects others. The listen function converts an unconnected socket into a passive socket and waits for the connection. Call listen to change the socket from closed state to listen state.

4. When the request arrives, call the accept function to copy the socket and process the request

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

Generally, the first parameter of the function is called a listening socket, and the socket returned by the function is called a connected socket. A server has only one listening socket to listen to the connection request of the client. The server kernel maintains a connected socket for each client's TCP connection, which is used to realize two-way data communication.

5. Data communication

The socket returned by accept is used for data communication. That is, IO operation.

client side

        1. Create socket

Same as TCP

This socket is the socket used to send requests to the server.

        2. Use the created socket to send a connection request to the server

        int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

The second parameter of the function is a structure that holds the ip address and port number of the object sending the connection request.

        3. Data communication using socket

server side simple example code

int main(int argc, const char *argv[])
{
	int fd = -1;
	struct sockaddr_in sin;
	int ret ;
	/*1.Create socket socket socket*/
	if((fd = socket(AF_INET,SOCK_STREAM,0)) == -1)
	{
		perror("socket");
		exit(1);
	}
	/*2.bind Bind, fill SOCKADDR before binding_ In this structure*/
			/*2.1   sin_zero The last eight digits should be set to zero*/
	bzero(&sin,sizeof(sin));
			/*2.2   Specify IPV4 programming domain*/
	sin.sin_family = AF_INET;
			/*2.3   Fill in the port number*/
	sin.sin_port = htons(5001);
			/*2.4   Fill in the network address in sin sin_ addr. s_ In addr*/
	sin.sin_addr.s_addr = inet_addr("192.168.1.3"); /*inet_addr Function is only applicable to IPV4*/
	
#if 0
    inet_pton(AF_INET,"127.0.0.1",(void *)&sin.sin_addr.s_addr);/*inet_pton You can use IPV6*/
#endif	

#if 0	
    sin.sin_addr.s_addr = htonl(INADDR_ANY);   
    /*Just bind INADDR_ANY, just manage a socket. No matter which network card the data comes from, the data can be received as long as it comes from the bound port number.*/
#endif

            /*2.5 Finally, bind*/
	if(bind(fd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
	{
		perror("bind");
		exit(1);
	}
 	
	/*3.listen Turn active socket into passive socket*/
	if(listen(fd,5) < 0)
	{
		perror("listen");
		exit(1);
	}
	/*4.Blocking waiting for client link requests*/
	int newfd = -1;
	newfd = accept(fd,NULL,NULL);   /*The two nulls do not care about the ip and port number of the client, so they are NULL*/
	if(newfd < 0)
	{
		perror("accept");
		exit(1);
	}
	/*5.Reading and writing*/
	ret = -1;
	char buf[255];
	while(1)
	{
		bzero(buf,255);
		do
		{
			ret = read(newfd,buf,255 - 1);
			}while(ret < 0 && errno != EINTR);
		if(ret < 0)
		{	
			perror("read");
			exit(1);
		}
		if(!ret)  //The other side to close
		{
			break;
		}
		printf("Receive data :%s\n",buf);
		if(!strncasecmp(buf,"quit",4))
		{
			break;
		}
	}
	close(newfd);
	close(fd);
	return 0;
}

client side simple example code

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <errno.h>

int main(int argc, const char *argv[])
{
	int fd = -1;
	struct sockaddr_in sin;
	int ret ;
	/*1.Create socket socket socket*/
	if((fd = socket(AF_INET,SOCK_STREAM,0)) == -1)
	{
		perror("socket");
		exit(1);
	}
  	/*2.Link server*/
	bzero(&sin,sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(5001);
	sin.sin_addr.s_addr = inet_addr("192.168.1.3"); /*Only for IPV4*/
	/*inet_pton(AF_INET,"127.0.0.1",(void *)&sin.sin_addr.s_addr);*/
	/*Finally, send the connection request*/
	if(connect(fd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
	{
		perror("connect");
		exit(1);
	}
 	
	/*3.Reading and writing*/
	ret = -1;
	char buf[255];
	while(1)
	{
		bzero(buf,255);
		if(fgets(buf,256,stdin) == NULL)
		{
			continue;
		}
		ret = write(fd,buf,strlen(buf));
		if(!strncasecmp(buf,"quit",4))
		{
			break;
		}
	}
	/*Close socket*/
	close(fd);
	return 0;
}

Existing problems

The read function on the server has a blocking function. When a client connects to the server and the server reads, the program always blocks at read. If another client requests to connect to the server, the server accept function is not executed, so the client cannot be connected. This means that concurrency cannot be achieved. The improved method can be solved by multithreading, multi process programming and other methods.

Topics: network