LINUX.ORG.RU

SOCK_STREAM и особенности работы с ним

 , , ,


1

3

Правильно ли я понимаю, что если есть такой серверный алгоритм:

int sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

struct sockaddr_in {
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};

sockaddr_in addr = { AF_INET, htons(port), { htonl(INADDR_ANY) } };
bind(sfd, &addr, sizeof(addr));

while (working) {
    sockaddr_storage peer;
    socklen_t sockLen = sizeof(peer);

    int fd = accept(sfd, &peer, &sockLen);
    if (fd != -1) {
        #define BUF_SIZE 256
        char buf[BUF_SIZE];

        ssize_t size = recv(fd, buf, BUF_SIZE, MSG_WAITALL);
        if (size != -1) {
            cout << "Got message: " << buf << endl;
        }

        close(fd);
    }
}

close(sfd);
* Тут я упростил всё во благо читабельности.

То клиент, чтоб отослать сообщение, должен каждый раз создавать новый сокет и писать в него? Т.е.:

void sendMessage(const std::string &message) {
    int sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    sockaddr_in addr = { AF_INET, htons(port), { htonl(INADDR_LOOPBACK) } };
    connect(sfd, &addr, sizeof(addr));

    send(sfd, message.c_str(), message.size(), 0);

    close(sfd);
}

P.S. В реальном коде использую getaddrinfo() + AF_UNSPEC.

★★★★★

Последнее исправление: KennyMinigun (всего исправлений: 3)

Ответ на: комментарий от devsdc

У меня на локалхосте сервер залипает на accept пока клиент не закроет файловый дескриптор.

Я конечно подумывал заюзать fsync или ioctl чтоб флашнуть файловый дескриптор, но не пробовал. Значит и пробовать не стоит?

KennyMinigun ★★★★★
() автор топика
Ответ на: комментарий от vromanov

А зачем так?

Честно говоря, не понял вопроса. Но у меня есть сервер и куча клиентов. Клиенты время от времени посылают серверу небольшие текстовые сообщения.

KennyMinigun ★★★★★
() автор топика
Последнее исправление: KennyMinigun (всего исправлений: 1)
Ответ на: комментарий от KennyMinigun

Мне просто кажется странным применение блокирующих сокетов. Также обычно делают в запросе заголовк с размером сообщения и ждут пока придет нужное количество байт.

vromanov ★★
()
Ответ на: комментарий от vromanov

Мне просто кажется странным применение блокирующих сокетов

Это у меня будет следующим этапом развития :)

Также обычно делают в запросе заголовк с размером сообщения и ждут пока придет нужное количество байт.

Спасибо за совет. Мне, по идее, должно хватить проверки что пришёл завершающий '\0' для строки.

А какая логика будет при работе с неблокирующими сокетами? Крутить цикл вокруг recv пока байты не закончатся?

KennyMinigun ★★★★★
() автор топика
Ответ на: комментарий от KennyMinigun

тебе неблокирующие сокеты нужны

Reset ★★★★★
()
Ответ на: комментарий от frugurt

Еще рекомендую посмотреть на libev. Вот пример http://codefundas.blogspot.ru/2010/09/create-tcp-echo-server-using-libev.html Очень годная штука для серверов типа такого. Ну и хоршо бы использовать стандартный проткол типа HTTP. Тогда можно сделать сервер в виде, например, модуля для nginx. Будет ЗНАЧИТЕЛЬНО удобнее тестировать и сопровождать

vromanov ★★
()
Ответ на: комментарий от vromanov

Тогда можно сделать сервер в виде, например, модуля для nginx. Будет ЗНАЧИТЕЛЬНО удобнее тестировать и сопровождать

IMHO кишки nginx делают тестирование и сопровождение кода сложнее. В случае с libevent/libev хотя бы есть документация.

i-rinat ★★★★★
()

send(,,,0);

write(,,);

anonymous
()

Да, ты понимаешь правильно.

Если вместо WAITALL+close использовать какую-нибудь другую логику для разделения сообщений (указывать длину сообщения в байтах, или использовать какой-нибудь разделитель), то переустановки соединения можно будет избежать :-).

ei-grad ★★★★★
()
Ответ на: комментарий от i-rinat

Мы наделали уже кучу серверов на nginx. Пример на freepcrf.com. проблема с отладкой, когда ты что-то уж совсем хитрое делаешь. А просто обработать запросы - вообще легко.

vromanov ★★
()
Ответ на: комментарий от i-rinat

Да там есть куча примеров. Собственно что нужно то - принять запрос, распарсить аргументы и выдать ответ. На это делается простейшая обертка.

static ngx_int_t handle_getTraceFilter(ngx_http_request_t * r) {
    OUT_BUFF_JSON_NGINX(json, r);
    CHECK_RETCODE_PROVISIONING(json_provisioning_result_start(&json, "FILTER", JSON_LEVEL_TYPE_OBJECT));
    CHECK_RETCODE_PROVISIONING(trace_dump_filter(&json));
    CHECK_RETCODE_PROVISIONING(json_provisioning_result_end(&json));
    SEND_BUFF(json.out_buff);
}
static ngx_int_t handle_setTraceFilter(ngx_http_request_t * r) {
    char subscribers[MAX_FILTER_SUBSCRIBERS_LIST_LEN + 1];
    char hosts[MAX_FILTER_HOSTS_LIST_LEN + 1];
    char info[MAX_FILTER_INFO_LEN + 1];
    PROVISIONING_ARG_STR("SUBSCRIBERS", subscribers);
    PROVISIONING_ARG_STR("HOSTS", hosts);
    PROVISIONING_ARG_STR("INFO", info);
    CHECK_RETCODE_ERROR_PROVISIONING(trace_filter_set(subscribers, hosts, info));
    return handle_getTraceFilter(r);
}

vromanov ★★
()
Ответ на: комментарий от KennyMinigun

А какая логика будет при работе с неблокирующими сокетами?

Странно, boost::asio еще не предложили. Погляди его, тебе будет проще, чем делать это вручную.

Pavval ★★★★★
()
Ответ на: комментарий от Pavval

Странно, boost::asio еще не предложили.

Может потому-что это бяка и никто не хочет советовать бяку?

Погляди его, тебе будет проще, чем делать это вручную.

На эрланге прямо в шеле можно запилить за 20 с половиной секунд. сплюс-сплюс посасывает.

nanoolinux ★★★★
()
Ответ на: комментарий от nanoolinux

На эрланге прямо в шеле можно запилить за 20 с половиной секунд. сплюс-сплюс посасывает.

Это очень умно в техническом треде про С++ начинать советовать другой ЯП.

Может потому-что это бяка и никто не хочет советовать бяку?

Если у тебя есть обоснования в рамках С++ - изволь их говорить сразу. Если ты про все тот же эрланг - просто свали с треда и не оффтопь.

Pavval ★★★★★
()

Как много времени было бы сэкономлено, если бы люди научились читать info libc, раздел «server example»

kawaii_neko ★★★★
()
Ответ на: комментарий от Pavval

Это очень умно в техническом треде

Кто бы говорил. Что ты забыл в этом треде?

Если у тебя есть обоснования в рамках С++

У чувака фундаментальный вопрос о том, как работает tcp accept, а ты ему суёшь свой повёрнутый буст. Ты надеешься, что буст решит проблему отсутствия знаний в его голове? Верх приплюснутости!

nanoolinux ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.