Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Клиент создает одно соединение, но принимается три 
:(
    Опции темы
Aoizora
Дата 11.12.2016, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 18.11.2016

Репутация: нет
Всего: нет



Пишу программу для удаленного администрирования по сети. Сервер запускается на моем компьютере, который находится за НАТом, клиент может быть где угодно. Для подключения к себе использую Dynamic DNS. Проброс портов настроил так: (роутер D-Link DIR-620, админка с темным дизайном)

user posted image

Мой сервер работает на порту 666, к нему делается проброс через порт 55000 из внешней сети.

Исходники клиента и сервера:

Сервер:
Код

#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <Windows.h>
#include <stdio.h>
#include <stdint.h>

#pragma comment(lib, "ws2_32.lib")

#define LOCAL_PORT 666
#define DEFAULT_PORT "666"    /* Must be the same as PORT */
#define MAX_CONNECTIONS 10

BOOL WINAPI InitWinSock();
void WINAPI FormatError(DWORD error);
SOCKET WINAPI BindSocket(uint16_t port);
DWORD WINAPI HandleConnection(LPVOID sock);
void WINAPI PrintClientInfo(sockaddr_in *addr);

int main(int argc, char *argv[])
{
    SOCKET server;
    SOCKET client;
    DWORD ThreadID;
    sockaddr_in client_addr;
    int addr_len = sizeof(client_addr);

    if (InitWinSock())
    {
        server = BindSocket(LOCAL_PORT);
        if (listen(server, MAX_CONNECTIONS) == SOCKET_ERROR)
        {
            FormatError(WSAGetLastError());
            WSACleanup();
            return -1;
        }

        printf("Acception loop\n");
        while (TRUE)
        {
            client = accept(server, (struct sockaddr *)&client_addr, &addr_len);
            printf("Accepted!\n");
            if (client != INVALID_SOCKET)
            {
                PrintClientInfo(&client_addr);
                CreateThread(NULL, 0, HandleConnection, &client, NULL, &ThreadID);
            }
        }
        WSACleanup();
    }
}

BOOL WINAPI InitWinSock()
{
    WSADATA wsadata;
    if (FAILED(WSAStartup(MAKEWORD(2, 2), &wsadata)))
    {
        FormatError(WSAGetLastError());
        return FALSE;
    }
    return TRUE;
}

void WINAPI FormatError(DWORD errCode)
{
    char error[1000]; 
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 
        NULL,
        WSAGetLastError(),
        MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
        error, sizeof(error), NULL);
    printf("\nError: %s\n", error);
}

SOCKET WINAPI BindSocket(uint16_t port)
{
    SOCKET sock = INVALID_SOCKET;
    sockaddr_in local_addr;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET)
    {
        FormatError(WSAGetLastError());
    }
    else
    {
        RtlZeroMemory(&local_addr, sizeof(local_addr));
        local_addr.sin_family = AF_INET;
        local_addr.sin_port = htons(port);
        local_addr.sin_addr.s_addr = INADDR_ANY;

        if (bind(sock, (struct sockaddr *)&local_addr, sizeof(local_addr)) == SOCKET_ERROR)
        {
            FormatError(WSAGetLastError());
        }
        else
        {
            printf("Server running on port %u address %s...\n", local_addr.sin_port, inet_ntoa(local_addr.sin_addr));
        }
    }

    return sock;
}

DWORD WINAPI HandleConnection(LPVOID sock)
{
    SOCKET client;
    HANDLE hFile = NULL;
    char buffer[200];
    int recv_bytes = 0;
    DWORD bytes_written = 0;

    printf("Handle connection...\n");

    client = *(SOCKET *)sock;
    
    char msg[] = "hello";
    send(client, msg, sizeof(msg), 0);

    shutdown(client, SD_BOTH);
    closesocket(client);

    printf("Connection closed\n");

    return 0;
}

void WINAPI PrintClientInfo(sockaddr_in *addr)
{
    char hostname[NI_MAXHOST];

    getnameinfo((struct sockaddr *)addr, sizeof(*addr), hostname, sizeof(hostname), NULL, 0, 0);
    printf("+ %s [%s] new connection\n", hostname, inet_ntoa(addr->sin_addr));
}



Клиент:
Код

#include <Ws2tcpip.h>
#include <stdio.h>
#include <stdint.h>
#include "auth.h"
#include "error.h"

#pragma comment(lib, "ws2_32.lib")

#define LOCAL_PORT 667
#define REMOTE_HOST "имя.ddns.net"
#define REMOTE_PORT 55000
#define DEFAULT_PORT "55000"    /* Must be the same as REMOTE_PORT */
#define MAX_CONNECTIONS 10

SOCKET WINAPI BindSocket(uint16_t port);
DWORD WINAPI HandleConnection(LPVOID sock);
void WINAPI BackConnect(char *hostname);

int main(int argc, char *argv[])
{
    WSADATA wsadata;
    SOCKET server;
    SOCKET client;
    DWORD ThreadID;
    sockaddr_in client_addr;
    int addr_len = sizeof(client_addr);

    if (FAILED(WSAStartup(MAKEWORD(2, 0), &wsadata)))
    {
        FormatError(WSAGetLastError());
    }
    else
    {
        server = BindSocket(LOCAL_PORT);
        if (listen(server, MAX_CONNECTIONS) == SOCKET_ERROR)
        {
            FormatError(WSAGetLastError());
            WSACleanup();
            return -1;
        }

        printf("Listening port %d...\n", LOCAL_PORT);

        BackConnect(REMOTE_HOST);
        while (TRUE)
        {
            client = accept(server, (struct sockaddr *)&client_addr, &addr_len);
            if (client != INVALID_SOCKET)
            {
                CreateThread(NULL, 0, HandleConnection, &client, NULL, &ThreadID);
            }
        }
        WSACleanup();
    }
}

SOCKET WINAPI BindSocket(uint16_t port)
{
    SOCKET sock = INVALID_SOCKET;
    sockaddr_in local_addr;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET)
    {
        FormatError(WSAGetLastError());
    }
    else
    {
        RtlZeroMemory(&local_addr, sizeof(local_addr));
        local_addr.sin_family = AF_INET;
        local_addr.sin_port = htons(port);
        local_addr.sin_addr.s_addr = INADDR_ANY;

        if (bind(sock, (struct sockaddr *)&local_addr, sizeof(local_addr)) == SOCKET_ERROR)
        {
            FormatError(WSAGetLastError());
        }
        else
        {
            printf("Server running...\n");
        }
    }

    return sock;
}

BOOL MyCmp(char *s1, char *s2)
{
    for (int i = 0; *s1 && *s2; s1++, s2++)
        if (*s1 != *s2)
            return FALSE;
    return TRUE;
}

DWORD WINAPI HandleConnection(LPVOID sock)
{
    SOCKET client = INVALID_SOCKET;
    HANDLE hFile = NULL;
    char buffer[200];
    DWORD bytes_written = 0;
    int auth_flag = 0;

    client = *(SOCKET *)sock;

    SendData(client, "command>");

    while (TRUE)
    {
        ZeroMemory(buffer, sizeof(buffer));
        int recv_bytes = recv(client, buffer, sizeof(buffer), 0);
        if (recv_bytes > 0)
        {
            if (MyCmp(buffer, "exit"))
            {
                printf("command: exit\n");
                break;
            }
            else if (MyCmp(buffer, "help"))
            {
                printf("command: help\n");
                SendData(client, "\thello\r\n");
            }
            else if (MyCmp(buffer, "auth"))
            {
                auth_flag = AuthProc(client);
            }
        }
        else break;

        SendData(client, "command>");
    }

    closesocket(client);
    printf("Connection closed\n");

    return 0;
}

void WINAPI BackConnect(char *hostname)
{
    struct addrinfo *result = NULL;
    struct addrinfo *ptr = NULL;
    struct addrinfo hints;
    struct sockaddr_in *remote_addr_ptr = NULL;
    SOCKET sock = INVALID_SOCKET;

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    getaddrinfo(hostname, DEFAULT_PORT, &hints, &result);
    ptr = result;

    if (ptr->ai_family == AF_INET)
    {
        remote_addr_ptr = (struct sockaddr_in *)ptr->ai_addr;
        printf("IPv4 address %s, port %u\n", inet_ntoa(remote_addr_ptr->sin_addr), remote_addr_ptr->sin_port);

        sock = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (sock == INVALID_SOCKET)
        {
            FormatError(WSAGetLastError());
        }
        else
        {
            //remote_addr_ptr->sin_addr.s_addr = inet_addr("127.0.0.1");
            remote_addr_ptr->sin_port = htons(REMOTE_PORT);
            if (connect(sock, (struct sockaddr *)remote_addr_ptr, sizeof(*remote_addr_ptr)) == SOCKET_ERROR)
            {
                printf("Connection to %s port %u failed\n", inet_ntoa(remote_addr_ptr->sin_addr), remote_addr_ptr->sin_port);
                FormatError(WSAGetLastError());
            }
            else
            {
                char szComputerName[MAX_PATH];
                DWORD dwSize = MAX_PATH / sizeof(TCHAR);

                GetComputerNameA(szComputerName, &dwSize);
                SendData(sock, szComputerName);
            }
            closesocket(sock);
        }
    }
}


Проблема возникает при соединении клиента с сервером. Сейчас и клиент и сервер находятся на моем компютере несмотря на то, что соединение происходит через Dynamic DNS. Вот скрины:

Это на сервере
user posted image

Это на клиенте

user posted image

Почему на сервере появляется три сообщения о подключении, если клиент создает только одно? Почему на клиенте функция connect завершается с ошибкой, а WSAGetLastError говорит, что операция завершена успешно?

Это сообщение отредактировал(а) Aoizora - 11.12.2016, 13:57
PM MAIL   Вверх
feodorv
Дата 11.12.2016, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2213
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Это точно клиент??? Зачем ему listen()???
Цитата(Aoizora @  11.12.2016,  13:56 Найти цитируемый пост)
if (listen(server, MAX_CONNECTIONS) == SOCKET_ERROR)
        {
            FormatError(WSAGetLastError());
            WSACleanup();
            return -1;
        }



Цитата(Aoizora @  11.12.2016,  13:56 Найти цитируемый пост)
Почему на сервере появляется три сообщения о подключении, если клиент создает только одно? Почему на клиенте функция connect завершается с ошибкой, а WSAGetLastError говорит, что операция завершена успешно?
Ох. Ну Вы же точно можете отлокализовать вывод сообщений об ошибках. И, определив место, догадаться, что к чему. Например:
Код

if (bind(sock, (struct sockaddr *)&local_addr, sizeof(local_addr)) == SOCKET_ERROR)
        {
            printf( "Error source: file = %s, line = %d\n", __FILE__, __LINE__);
            FormatError(WSAGetLastError());
        }
Или:
Код

void WINAPI FormatError(DWORD errCode, const char *fileName, int lineNumber)
{
    char error[1000]; 
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 
        NULL,
        WSAGetLastError(),
        MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
        error, sizeof(error), NULL);
    printf("\nError: %s\n(file = %s, line = %d)\n", error, fileName, lineNumber);
}


Добавлено через 1 минуту и 36 секунд
Код

FormatError(WSAGetLastError(), __FILE__, __LINE__);



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Google
  Дата 21.5.2019, 13:31 (ссылка)  





  Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0784 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.