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;
}

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

accept в цикл помести.

Deleted ()

Всё логично. Ты делаешь 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

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

i-rinat ★★★★★ ()
Ответ на: комментарий от 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 ★★★★★ ()
Ответ на: комментарий от ITmuha

а зачем «ты только начинаешь изучать с++»?

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