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 ...
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
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;
}
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
.
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 the
getaddrinfo function` is errno, so if you do it properly, you should receive it.
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.
This is also a habit.
Associate the address received by the bind function
with the socket.
Now you are ready to receive.
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.
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.
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