LINUX.ORG.RU

TCPSERVER

 ,


0

1

У меня проблемы с TCP сервером

  • После отключения клиента от сервера,сервер отключается.Нужно чтобы сервак продолжал работать.
  • Клиент подключается по порту 1234,но в терминале показывает,что клиент подключился по другому(каждый раз разные порты)
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <string>
 
using namespace std;
 
int main()
{
    // Create a socket
    int listening = socket(AF_INET, SOCK_STREAM, 0);
    if (listening == -1)
    {
        cerr << "Can't create a socket! Quitting" << endl;
        return -1;
    }
 
    // Bind the ip address and port to a socket
    sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(1234);
    inet_pton(AF_INET, "0.0.0.0", &server.sin_addr);
 
    bind(listening, (sockaddr*)&server, sizeof(server));
 
    // Tell Winsock the socket is for listening
    listen(listening, SOMAXCONN);
 
    // Wait for a connection
    sockaddr_in client;
    socklen_t clientSize = sizeof(client);
 
    int clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
 
    char host[NI_MAXHOST];      // Client's remote name
    char service[NI_MAXSERV];   // Service (i.e. port) the client is connect on
 
    memset(host, 0, NI_MAXHOST); // same as memset(host, 0, NI_MAXHOST);
    memset(service, 0, NI_MAXSERV);
 
    if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
    {
        cout << host << " connected on port " << service << endl;
    }
    else
    {
        inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
        cout << host << " connected on port " << ntohs(client.sin_port) << endl;
    }
 
    // Close listening socket
    close(listening);
 
    // While loop: accept and echo message back to client
    char buf[4096];
 
    while (true)
    {
        memset(buf, 0, 4096);
 
        // Wait for client to send data
        int bytesReceived = recv(clientSocket, buf, 4096, 0);
        if (bytesReceived == -1)
        {
            cerr << "Error in recv(). Quitting" << endl;
            break;
        }
 
        if (bytesReceived == 0)
        {
            cout << "Client disconnected " << endl;
            break;
        }
 
        cout << string(buf, 0, bytesReceived) << endl;
 
        // Echo message back to client
        send(clientSocket, buf, bytesReceived + 1, 0);
    }
 
    // Close the socket
      close(clientSocket);
   
 
    return 0;
}

Всё логично. Ты делаешь recv(), он возвращает законный 0, ты выходишь. Более того, выход из цикла может быть даже до отключения клиента. Думай, как уведомить сервер об отключении клиента и меняй логику работы сервера

XMs ★★★★★ ()

После отключения клиента от сервера,сервер отключается.

от чего? или от кого? и от чего или кого он не должен отключаться?

Нужно чтобы сервак продолжал работать.

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

Клиент подключается по порту 1234,но в терминале показывает,что клиент подключился по другому(каждый раз разные порты)

У Вrас putty пробелы проглатывает. И подземный стук.

mos ★★☆☆☆ ()

Прочитай про select и используй его.
Получив ничего от клиента, выкидывай клиента из списка fd в select.
Клиент на твой «сервер» коннектится со случайного порта >1023, ты его печатаешь. Ну и чего ж ты хочешь?

Рекламная пауза: возьми у ленина его авторский курс по использованию гугла и найди пример написания tcp-сервера на c++.

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

Рекламная пауза: возьми у ленина его авторский курс по использованию гугла и найди пример написания tcp-сервера на c++.

В коде кстати никакого C++ нет, если не считать cerr cout

SZT ★★★★ ()
Последнее исправление: SZT (всего исправлений: 1)

После отключения клиента от сервера,сервер отключается.

ну так у тебя проге так и написано,напиши чтобы не отключался.

Клиент подключается по порту 1234,но в терминале показывает,что клиент подключился по другому(каждый раз разные порты)

твой сервер слушает порт 1234,а клиенты подключаются с какого удобно.

jo_b1ack ★★★★ ()

close(listening);

После отключения клиента от сервера,сервер отключается.

У меня проблемы с TCP сервером

Это не проблемы с TCP-сервером. Это попытка решить учебное задание с помощью форума. Не надо так делать. Смысл учебных заданий состоит в обучении.

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

Я не верю. Это либо учебное задание, либо кусок программы из учебника в том месте, где ещё не объясняется, как исправить сервер так, чтобы обслуживать несколько клиентов.

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

Да всем пофиг, что это и зачем оно тебе надо. Эту херню любой первокурсник должен уметь. Не умеешь — читай учебник. Не хочешь — иди за деньги в job.

anonymous ()
Ответ на: комментарий от ITmuha

Я наверное написал чтобы получить помощь,а не обсуждать зачем мне это надо

То есть, ты не уверен?

Допустим, тебе действительно помощь нужна не в том, чтобы зачёт сдать. В каком виде ты её ожидаешь? Хочешь, чтобы тебе готовый листинг программы написали, что ли?

i-rinat ★★★★★ ()

в info-pages (сиречь в вашем дистрибутиве, на вашем компе) есть детально разобранные и разжёванные примеры, tcpserver и tcpclient.

info socket

PS/ для тех кто в танке юн и зелен - info это такие расширенные man`ы, часть классической документации GNU.

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

если это не учебное задание, то используй xinetd для запуска сервера. тогда твоей серверной программе о сокетах вообще ничего знать не надо, только stdin, stdout

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

Да чего там дебажить-то? У него вся логика написана так, чтобы принять одно соединение, почитать чего отправили, ответить и схлопнуться. Думаю, он просто пример где-то скопипастил и ничего не понял.

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

А то, что тебе посоветовали, ты понял? В любом случае, тебе нужен цикл. Более сложный, но правильный, вариант — использовать select и обрабатывать входящие соединения (accept) и сообщения (recv) в одном цикле, более простой, хоть и не кошерный, но тебе будет понятней, — запускать поток на каждое входящее соединение и обрабатывать его уже в нём.

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

Там весь код нужно редактировать. Все системные вызовы возвращают что-нибудь. И в подавляющем большинстве случаев нужно проверять, что они возвратили, потому что это важно. Например, send не обязан обрабатывать весь буфер, который ему передали. Он возвращает число отосланных байт.

Я советую прочитать, что вообще делают вызываемые функции, что принимают, что возвращают.

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

Про всякие процессы, сокеты, файлы и прочее: Michael Kerrisk, Linux Programming Interface. Читал, понравилось. На английском. Нужны базовые знания C.

Больше ничего советовать не буду, качество не проверял. Гугли и выбирай сам.

Документация к языкам программирования https://toster.ru/q/463026 https://rsdn.org/article/unix/sockets.xml

anonymous ()

Не нужен тут селект, если клиенты приходят последовательно. Вообще не стоит в это лезть, пока нет представления о программировании в целом и C в частности.

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

Не нужен тут селект, если клиенты приходят последовательно.

А если клиент один и приходит только один раз, то вообще ничего менять не надо — и так сработает.

frob ★★★★★ ()