Computer network - top-down notes - socket programming

Socket programming 🐣

Because socket programming is very huge, this paper, as a learning note, only realizes the relatively simple and basic part, but I hope it will be helpful to you

Links to all computer network learning notes

Sockets are different when identifying communication endpoints

  • External: use IP address + port number
  • Internal: use socket descriptor for identification

Socket address structure:

//IP socket address structure
//sockaddr_in: Internet socket address
struct sockaddr_in {
  uint_16_t			 sin_family;			//protocol family
  uint_16_t			 sin_port;				//port
  struct in_addr sin_addr;				//32-bit IP address
  unsigned char  sin_zero[8];			//sizeof (struct sockaddr)

//Used for: connect, bind, accept
struct sockaddr {
  uint16_t			safamily;
  char 					sa_data[14];

In the connect, bind and accept functions, a pointer to the socket address structure related to the protocol is required. We set a general sockaddr data structure pointer, and then forcibly convert it into this general pointer when indicating the socket address (so that it can accept various types of socket address structures)

Explanation of socke function


Create a socket with the following functions

AF_INET indicates that we are using a 32-bit IP address

#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol)
#The non negative descriptor is returned successfully, and - 1 is returned in case of error
clientfd = socket(SF_INET, SOCK_STREAM, 0);		//default : 0


The following bind, listen, accept: the server uses these functions to establish a connection with the client

The bind function tells the kernel to associate the server socket address in addr with the socket descriptor sockfd

#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr * addr, socklen_t addrlen);
#0 returned successfully and - 1 returned in error


The listen function is used to tell the kernel that the socket descriptor is used by the server rather than the client

The listen function converts sockfd from an active socket to a listening socket, which receives requests from clients.

The backlog indicates the number of queued connections

#include <sys/socket.h>
int listen(int sockfd, int backlog);

#0 if successful, or - 1 if not


The server waits for the connection request from the client by calling the accept function

The non negative connection descriptor (connected descriptor) is returned, that is, a new socket is created to communicate with the client socket separately. The original listening descriptor continues to wait for applications from new clients, so that many client applications can be processed at the same time

#include <sys/socket.h>

int accept(int listenfd, struct sockaddr * addr, int * addrlen);

#The non negative connection descriptor is returned on success, and - 1 is returned on error

The read & write function is called differently, which is to interact with each other

#Read is used to read data
ssize_t read (int fd, void * buf, size_t count);

#Write is used to write data, which is also blocking
ssize_t write(int fd, const void * buf, size_t count);

The client establishes a connection with the server whose socket address is addr by calling the connect function

The connect function will block until the connection succeeds or an error occurs

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

Host byte order and network byte order are converted to each other

In order to get the correct explanation when the program is transmitted between different hosts 🦁 In addition, byte order conversion is required

uint32_t htonl(uint32_t hostlong);   //32-bit host to network
uint16_t htons(uint16_t hostshort);  //16 bit host to network
uint32_t ntohl(uint32_t netlong);    //32-bit network to host
uint16_t ntohs(uint16_t netshort);   //16 bit network to host

Socket case

A scenario in which a peer-to-peer client sends information to the server, and then the server copies and resends the content

s e r v e r . c server.c server.c

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>

const int MYPORT = 8887;
const int QUEUE  = 20;
const int BUFFER_SIZE = 20;

(2) struct sockaddr_in(IP Dedicated address structure)

structsockaddr_in {

u_char    sin_len;//length

u_short   sin_family;//agreement

u_short    sin_port;//port

structin_addr   sin_addr;//ip address

char   sin_zero[8];//data


(3) struct in_addr

structin_addr {undefined


//Server_addr: indicates the remote IP address and port number
int main()
    //Created socket
    int server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
    //Define sockaddr_in
    struct sockaddr_in server_sockaddr;
    server_sockaddr.sin_family = AF_INET;
    server_sockaddr.sin_port = htons(MYPORT);       //Conversion function of port
    server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);    //IP address
    //bind returns 0 successfully and - 1 in case of error
    if (bind(server_sockfd, (struct sockaddr *) & server_sockaddr, sizeof(server_sockaddr)) == -1) {
    printf ("monitor:%d port\n", MYPORT);
    //listen returns 0 if it succeeds and - 1 if it fails 
    if (listen(server_sockfd, QUEUE) == -1) {

    //Client socket
    char buffer[BUFFER_SIZE];
    struct sockaddr_in client_addr;     //The structure used to identify the client
    socklen_t length = sizeof (client_addr);

    printf("Waiting for client connection\n");

    //Success - > non negative return
    //Failed - > Return - 1
    int conn = accept(server_sockfd, (struct sockaddr*) & client_addr, & length);
    if (conn < 0) {
    printf("Client successfully connected\n");

    while (1) {
        memset(buffer, 0, sizeof (buffer));
        int len = recv(conn, buffer, sizeof (buffer), 0);
        //The client terminates and exits when sending exit
        if (strcmp (buffer, "exit\n") == 0 || len <= 0) {
        printf("Data from client:%s\n", buffer);
        send(conn, buffer, len, 0);
        printf("Data sent to client:%s\n", buffer);
    return 0;

c l i e n t . c client.c client.c

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>

#define MYPORT 8887
#define BUFFER_SIZE 1024
char * SERVER_IP = "";

int main()
    //Define sockfd
    int sock_cli = socket(AF_INET, SOCK_STREAM, 0);

    //Define sockaddr_in
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof (servaddr));

    servaddr.sin_family = AF_INET;      //Define protocol family
    servaddr.sin_port = htons(MYPORT);
    servaddr.sin_addr.s_addr = inet_addr(SERVER_IP);        //Server IP

    printf("connect%s: %d\n", SERVER_IP, MYPORT);
    //Connect to the server. 0 is returned successfully and - 1 is returned in error
    if (connect(sock_cli, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {

    printf("Server connection succeeded!\n");

    //The connection with the newly created socket on the server side is established
    char sendbuf[BUFFER_SIZE];
    char recvbuf[BUFFER_SIZE];

    while (fgets(sendbuf, sizeof (sendbuf), stdin) != NULL ) {
        printf("Send data to server: %s\n", sendbuf);
        send(sock_cli, sendbuf, strlen(sendbuf), 0);
        if (strcmp(sendbuf,"exit\n") == 0) {
            break;      //Enter exit to exit
        recv(sock_cli, recvbuf, sizeof(recvbuf), 0);
        printf("Receive data from server:%s\n", recvbuf);

        memset(sendbuf, 0, sizeof (sendbuf));
        memset(recvbuf, 0, sizeof (recvbuf));
    return 0;

reference material

Keywords: network computer networks

Added by verano on Sat, 05 Feb 2022 15:03:07 +0200