[LINUX] Set up a UDP server in C language

Set up a server in C language

It is difficult to set up a server in c language. The purpose of this article is to allow newcomers and people who have never written a server to move it for the time being and answer a few questions to some extent. If you have to build a server and are currently working, you can save time by copying the code below and rewriting it according to your business specifications. This time it will be very simple in UDP. I think this may not be enough for the actual requirements. However, it is easier to move forward when you are connected than when you have no hands or legs at all. From here, play around with the code that suits your requirements. There is no explanation in this article about what UDP is. There are so many explanations on the Internet that they are rotten, so please go there. For books, Computer Network 5th Edition is good, but the price and thickness are so ...

environment

I will put the environment I tried for the time being, but I think that it will work with relatively recent linux.

Ubuntu 18.04.2 LTS
gcc 7.4.0

Simple UDP server

UDP can be thought of as a simple TCP from an implementation perspective.

As a simple server

--Data is received from localhost`` 9002 --Display the received data

For the time being, the code that works if you copy and paste it looks like this.

#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>

#include <stdio.h>
#include <string.h>

int main ()
{
  //1.Build a receiving address
  struct addrinfo hints;
  memset (&hints, 0, sizeof (hints));
  hints.ai_socktype = SOCK_DGRAM;

  struct addrinfo *bind_address;
  getaddrinfo ("localhost", "9002", &hints, &bind_address);


  //2.Create a socket
  int  socket_listen;
  socket_listen = socket (bind_address->ai_family,
              bind_address->ai_socktype,
              bind_address->ai_protocol);
  if (socket_listen < 0)
  {
      fprintf (stderr, "socket() failed. (%d)\n", errno);
      return 1;
  }


  //3.Bind the local address to the socket
  if (bind (socket_listen, bind_address->ai_addr, bind_address->ai_addrlen))
  {
      fprintf (stderr, "bind() failed. (%d)\n", errno);
      return 1;
  }
  freeaddrinfo (bind_address);


  //4.Wait for client connection
  while (1)
  {
      struct sockaddr_storage client_address;
      socklen_t client_len = sizeof (client_address);

      char read[4096];
      memset(read, 0, sizeof(read));
      int bytes_received = recvfrom (socket_listen, read, 4096, 0,
                     (struct sockaddr *) &client_address,
                     &client_len);
      if (bytes_received < 1)
      {
        fprintf (stderr, "connection closed. (%d)\n", errno);
        return 1;
      }
      printf("receiving: %s", read);
  }

  //5.Close socket
  close(socket_listen);
  printf ("Finished.\n");

  return 0;
}

A little commentary

1. Build the receiving address

There are several ways to build a structure for connection.

--How to manually set members one by one --How to use the gethostbyname function --How to use the getaddrinfo function

This time, I built it by the third method.

There are three tasks to use the getaddrinfo function.

  1. Decide the receiving address
  2. Decide the receiving port number
  3. Define a hint ʻaddrinfo structure`

The ʻaddrinfo structurein 3 usually sets ip4 or ip6, TCP or UDP. If ip is 0, it becomes ip4. SOCK_DGRAM is adatagram, and when set, it becomes UDP. I haven't used it this time, but the return value of thegetaddrinfo function` is errno, so if you do it properly, you should receive it.

2. Create a socket

This is the one who writes with such a complete habit no matter who does it. A socket is a communication terminal (on a program), and the OS sends and receives through the socket. The socket function creates a socket descriptor. A socket descriptor is a type of file descriptor. A file descriptor is a unique number that allows the OS to handle files. linux treats various things as files. Text files, devices (USB memory, etc.), etc. To be able to read and write to the network in the same way as files It is the role of the socket descriptor. The return value of the socket function is the socket descriptor.

3. Bind the local address to the socket

This is also a habit. Associate the address received by the bind function with the socket. Now you are ready to receive.

4. Wait for the client to connect

The most important process. I'm sure we'll do various things here in this chan. Normally, the server is not dropped, so it loops infinitely. Use the recvfrom function to receive. The recvfrom function receives the source information. The sockaddr_storage structure is a structure that can be represented by either ip4 or ip6.

5. Close the socket

Like memory and threads, sockets leak, so you need to open them. The close function is used to close a file. Since the socket can also be treated as a file, it can be opened with the same close function as the file.

For the time being, the client

I feel like I don't need it. I'm reading the connect function even though it's UDP. In fact, you can use the connect function in UDP as well. You can also write using the connect function on the server. When you use the connect function in UDP, it behaves differently than when you use it in TCP. The explanation here is ... well.

#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>

#include <stdio.h>
#include <string.h>

int main(void)
{
    struct addrinfo hints;
    memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_DGRAM;
    struct addrinfo *peer_addr;

    if(getaddrinfo("localhost","9002",&hints, &peer_addr))
    {
        fprintf(stderr, "getaddrinfo() failed. (%d)\n", GETSOCKETERRNO());
        return 1;
    }

    char addrbuf[100];
    char servbuf[100];
    getnameinfo(peer_addr->ai_addr, peer_addr->ai_addrlen, addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), NI_NUMERICHOST);
    printf("%s %s\n", addrbuf, servbuf);

    puts("Creating socket");
    int socket_peer;
    socket_peer = socket(peer_addr->ai_family, peer_addr->ai_socktype, peer_addr->ai_protocol);
    if(!ISVALIDSOCKET(socket_peer))
    {
        fprintf(stderr, "socket() failed. (%d)\n", GETSOCKETERRNO());
        return 1;
    }

    if(connect(socket_peer,peer_addr->ai_addr, peer_addr->ai_addrlen))
    {
        fprintf(stderr,"connect() failed. (%d).\n", GETSOCKETERRNO());
        return 1;
    }

    freeaddrinfo(peer_addr);

    puts("Connected");

    while(1)
    {

        {
            char read[4096];
            if(!fgets(read, 4096, stdin)) break;

            int bytes = send(socket_peer, read, strlen(read), 0);
            printf("send %d bytes\n", bytes);
        }

    }
    puts("Closing socket");
    CLOSESOCKET(socket_peer);
    return 0;
}

Recommended Posts

Set up a UDP server in C language
Set up a simple HTTPS server in Python 3
Set up a test SMTP server in Python.
Set up a simple SMTP server in Python
Set up a free server on AWS in 30 minutes
Set up a Samba server with Docker
Set up a mail server using Twisted
Set up a simple HTTPS server with asyncio
Set up a local server with Go-File upload-
Set up a local server with Go-File download-
Set up a local web server in 30 seconds using python 3's http.server
How to set up a local development server
Create a web server in Go language (net/http) (2)
Set up a development environment for natural language processing
Try to make a Python module in C language
Set up a simple local server on your Mac
Set up a Minecraft resource (Spigot) server via docker (2)
Set up a file server on Ubuntu 20.04 using Samba
[Part 1] Let's set up a Minecraft server on Linux
Create a web server in Go language (net / http) (1)
Set up a Minecraft resource (Spigot) server via docker
[Vagrant] Set up a simple API server with python
Machine language embedding in C language
Heapsort made in C language
Set up Nunjucks in Node.js
How to display the modification date of a file in C language up to nanoseconds
I want to set up a mock server for python-flask in seconds using swagger-codegen.
Set up a web server with CentOS7 + Anaconda + Django + Apache
How to set up a simple SMTP server that can be tested locally in Python
Write a table-driven test in C
Multi-instance module test in C language
Realize interface class in C language
ABC166 in Python A ~ C problem
Solve ABC036 A ~ C in Python
Start SQLite in a programming language
Solve ABC037 A ~ C in Python
Segfault with 16 characters in C language
Introduction to Socket API Learned in C Language Part 1 Server Edition
Set up Ubuntu as a Linux cheat sheet and https server
Introduction to Socket API Learned in C Part 4 UDP Server / Client # 1
Linked list (list_head / queue) in C language
Solve ABC175 A, B, C in Python
Set up a dummy SMTP server in Python and check the operation of sending from Action Mailer
Send mail with mailx to a dummy SMTP server set up with python.
Set up Pipenv in Pycharm in Windows environment
Generate C language from S-expressions in Python
Set up a server that processes multiple connections at the same time
Behavior when SIGEV_THREAD is set in sigev_notify of sigevent with timer_create (C language)
I made a module in C language to filter images loaded by Python
Build a C language development environment with a container
Use a scripting language for a comfortable C ++ life
Create an executable file in a scripting language
How to multi-process exclusive control in C language
Set a fixed IP in the Linux environment
Call a Python script from Embedded Python in C ++ / C ++
Set up a Python development environment on Marvericks
I tried adding a Python3 module in C
Set up a file server using samba on ZeroPi of Friendly Arm [OS installation]
Set up an FTP server that can be created and destroyed immediately (in Python)
Set up a file server using samba on ZeroPi of Friendly Arm [Purchased Items]
Find a guideline for the number of processes / threads to set in the application server