C Socket Programming #3 – Live Server

Sun, Apr 23, 2017 4-minute read

In our previous post we established a connection with the client and ended it immediately afterwards. That is fine for a demo, but a real server should stick around, so in this post we will keep the socket we open actively handling connections.

A useful detail first: to find out the IP address of the connecting client, these 2 lines are enough. As mentioned in the first post, we perform data type conversions along the way.

char *client_ip = inet_ntoa(client.sin_addr);
int client_port = ntohs(client.sin_port);

The code below pulls together everything from the earlier posts: we create a socket and bind it to port 8888, start listening for connections with listen, accept the incoming connection with accept, write our message to that connection, and then end it.

#include<stdio.h>
#include<string.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>    //write
 
int main(int argc , char *argv[])
{
    int socket_desc , new_socket , c;
    struct sockaddr_in server , client;
    char *message;
     
    //Create socket
    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1)
    {
        printf("Could not create socket");
    }
     
    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( 8888 );
     
    //Bind
    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
    {
        puts("bind failed");
        return 1;
    }
    puts("bind done");
     
    //Listen
    listen(socket_desc , 3);
     
    //Accept and incoming connection
    puts("Waiting for incoming connections...");
    c = sizeof(struct sockaddr_in);
    new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
    if (new_socket<0)
    {
        perror("accept failed");
        return 1;
    }
     
    puts("Connection accepted");
     
    //Reply to the client
    message = "Hello Client , I have received your connection. But I have to go now, bye\n";
    write(new_socket , message , strlen(message));
     
    return 0;
}

The reply itself is handled with the write function, just as if writing to a file.

write takes 3 parameters: the address to write to, the content, and the size of the content.

To see it in action, if you are on a UNIX/LINUX-based operating system, you can reach the server we created by typing telnet localhost 8888.

And our message appears in front of us.

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello Client , I have received your connection. But I have to go now, bye
Connection closed by foreign host.

So far the server serves one client and quits. To keep it always active, we put the accept function inside a while loop, which lets more than one client connect.

while( (new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
    {
        puts("Connection accepted");
         
        //Reply to the client
        message = "Hello Client , I have received your connection. But I have to go now, bye\n";
        write(new_socket , message , strlen(message));
    }
     
    if (new_socket<0)
    {
        perror("accept failed");
        return 1;
    }
     
    return 0;

source: http://www.binarytides.com/socket-programming-c-linux-tutorial/

– Turkish Version –

C Soket Programlama #3 – Live Server

Önceki yazımızda client ile bağlantı kurmuş ve hemen sonlandırmıştık. Bu bir demo için yeterli, ama gerçek bir server ayakta kalmalı, o yüzden bu yazımızda açtığımız soket ile bağlantıları aktif olarak değerlendireceğiz.

Önce işe yarar bir ayrıntı: bağlanan clientin IP adresini öğrenmek için bu 2 satır bize yeterli olacak. İlk yazıda bahsettiğimiz gibi bu sırada veri tipi dönüşümleri yapıyoruz.

char *client_ip = inet_ntoa(client.sin_addr);
int client_port = ntohs(client.sin_port);

Aşağıdaki kod önceki yazılardaki her şeyi bir araya getiriyor: soket oluşturup onu 8888 numaralı porta bind ediyoruz, listen ile bağlantıları dinlemeye başlıyoruz, gelen bağlantıyı accept ile kabul ediyoruz, bu bağlantıya mesajımızı yazdırıp sonlandırıyoruz.

#include<stdio.h>
#include<string.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>    //write
 
int main(int argc , char *argv[])
{
    int socket_desc , new_socket , c;
    struct sockaddr_in server , client;
    char *message;
     
    //Create socket
    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1)
    {
        printf("Could not create socket");
    }
     
    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( 8888 );
     
    //Bind
    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
    {
        puts("bind failed");
        return 1;
    }
    puts("bind done");
     
    //Listen
    listen(socket_desc , 3);
     
    //Accept and incoming connection
    puts("Waiting for incoming connections...");
    c = sizeof(struct sockaddr_in);
    new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
    if (new_socket<0)
    {
        perror("accept failed");
        return 1;
    }
     
    puts("Connection accepted");
     
    //Reply to the client
    message = "Hello Client , I have received your connection. But I have to go now, bye\n";
    write(new_socket , message , strlen(message));
     
    return 0;
}

Cevabın kendisi, tıpkı dosyaya yazdırıyormuş gibi write fonksiyonuyla hallediliyor.

write 3 parametre alır. Bunlar yazdırılacak adres, içerik ve içeriğin boyutudur.

Çalışırken görmek için, eğer UNIX/LINUX tabanlı bir işletim sistemindeyseniz telnet localhost 8888 yazarak oluşturduğumuz servera erişebiliriz.

Ve karşımıza mesajımız gelir.

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello Client , I have received your connection. But I have to go now, bye
Connection closed by foreign host.

Şu haliyle server tek bir cliente hizmet edip kapanıyor. Bunu hep aktif tutmak için accept fonksiyonunu bir while döngüsü içine alıyoruz, böylelikle birden fazla client bağlanabiliyor.

while( (new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
    {
        puts("Connection accepted");
         
        //Reply to the client
        message = "Hello Client , I have received your connection. But I have to go now, bye\n";
        write(new_socket , message , strlen(message));
    }
     
    if (new_socket<0)
    {
        perror("accept failed");
        return 1;
    }
     
    return 0;

kaynak : http://www.binarytides.com/socket-programming-c-linux-tutorial/