Минимальный пример клиент-серверной программы

Для ясности изложения рассмотрим простейший вариант клиента и сервера (ниже обсуждается, что в этой реализации плохо). Задача сервера — принимать соединения на порт 1234. От каждого клиента принимается ровно одно сообщение и соединение с клиентом закрывается.

Начнем с сервера.

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>

int main(int argc, char *argv[])
{
    int as, ms;
    struct sockaddr_in server;
    char buf[1024]; /* буфер для приема сообщений от клиентов */

    as = socket(AF_INET, SOCK_STREAM, 0 ); /* Создаем сокет для работы по TCP/IP */

    /* Заполняем структуру адреса, на котором будет работать сервер */
    server.sin_family = AF_INET; /* IP */
    server.sin_addr.s_addr = INADDR_ANY; /* любой сетевой интерфейс */
    server.sin_port = htons(1234); /* порт */

    /* сопоставляем адрес с сокетом */
    bind(as, (struct sockaddr *) &server, sizeof(server));

    listen(as, 5); /* сокет as используется для приема соединений; 5 - длина очереди */

    /* цикл обработки клиентов */
    while( 1 ) {
        ms = accept( as, 0, 0 ); /* выбираем первое соединение из очереди */
        bzero( buf, sizeof(buf)); /* обнуляем буфер сообщения */
        read(ms, buf, sizeof(buf)); /* читаем сообщение от клиента */
        close( ms ); /* закрываем соединение с клиентом */
        printf("message is = %s\n", buf );
        if ( strcmp(buf, "quit") == 0 ) break;
    }
    close( as ); /* закрываем порт 1234; клиенты больше не могут подключаться */
    return 0;
}

Компилировать надо командой gcc -o server server.c
Простейший клиент для работы с таким сервером (компилировать командой gcc -o client client.c):
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    int s;
    struct sockaddr_in server;
    struct hostent *hp;

    if( argc<4 ) { return 1; } /* должно быть 3 аргумента: адрес, порт и сообщение */

    s = socket(AF_INET, SOCK_STREAM, 0 ); /* Создаем сокет для работы по TCP/IP */

    /* Заполняем струтуру с адресом сервера */
    server.sin_family = AF_INET; /* протокол IP */
    hp = gethostbyname(argv[1]); /* Обращаемся к DNS и узнаем адрес по символьному имени*/
    bcopy( hp->h_addr, &server.sin_addr, hp->h_length); /* копируем из hp->h_addr в &server.sin_addr hp->h_length байт */
    server.sin_port = htons(atoi(argv[2])); /* номер порта, на котором запущен сервер */

    connect(s, (struct sockaddr *)&server, sizeof(server)); /* устанавливаем соединение с сервером */
    write(s, argv[3], strlen(argv[3]) ); /* посылаем строчку */
    close( s );
    return 0;
}

Для запуска теста необходимо сначала запустить сервер командой ./server, а потом, в другом терминале (сервер у вас продолжает работать), запустить клиента
./client localhost 1234 "Unbelievable! It works!" 
При выполнении этой команды сервер должен напечатать текст сообщения (Unbelievable! It works!). Обратите внимание, что сообщение заключено в кавычки. В этом случае вся строка, которая содержит пробелы, считается одним аргументом командной строки. Если клиент посылает сообщение quit, то, как это видно из текста программы, сервер останавливается.

Как надо делать