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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помогите разобраться с ошибкой в коде сервера 
:(
    Опции темы
Scorp_progr
Дата 23.8.2007, 15:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



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

Как мне кажется проблема в функции SendMessageNCP() , а именно в АПИ функции WSASend() 


Очень жду ответов, заранее спасибо. 

Вот исходники

Сам класс CompletionPort
Код

// NetCompletionPort.h: interface for the NetCompletionPort class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_NETCOMPLETIONPORT_H__48039904_FFB7_44AA_AA5C_EE318620C63D__INCLUDED_)
#define AFX_NETCOMPLETIONPORT_H__48039904_FFB7_44AA_AA5C_EE318620C63D__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <stdio.h>
#include <conio.h>
#include <malloc.h>
#include <Winsock2.h>
#include <list>        // Используем STL
#include "NetDefine.h"
#pragma comment (lib,"ws2_32.lib")   // Линковка библиотеки ws2_32.lib
using namespace std;                 // Использовать пространство имен std


class NetCompletionPort  
{
public:
    int net_error;
    HANDLE hCp;      // описатель порта
    DWORD ThreadId;  // ИД потока сервера
    HANDLE hThread;  // хендл потока сервера
    SOCKET server_sock;
    
    NetCompletionPort();
    void Start();
    virtual ~NetCompletionPort();


};

#endif // !defined(AFX_NETCOMPLETIONPORT_H__48039904_FFB7_44AA_AA5C_EE318620C63D__INCLUDED_)
------------------------------------------------------------------------------------------------------
// NetCompletionPort.cpp: implementation of the NetCompletionPort class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "NetCompletionPort.h"

DWORD WINAPI ServerPool(HANDLE hp);
void Print(const char * str);

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

NetCompletionPort::NetCompletionPort()
{
    WORD wVersionRequested;  // Запрашиваемая версия
    WSADATA wsaData;         // Структура инф-ции о сокетах
    int err;

    //Инициализация библиотеки ws2_32.dll
    wVersionRequested=MAKEWORD(2,2);
    err=WSAStartup(wVersionRequested,&wsaData);
    if(err==SOCKET_ERROR)
    {
        net_error=-1;
        WSACleanup(); // Завершение работы
        return;
    }
    //Создаем порт завершения
    hCp=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
    if(hCp==NULL)
    {
        net_error=-1;
        WSACleanup(); // Завершение работы
        return;
    }
    // Задаем параметры для прослушивающего сокета сервера
    server_sock=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,NULL, WSA_FLAG_OVERLAPPED);
    if(server_sock==INVALID_SOCKET)
    {
        net_error=-1;
        WSACleanup(); //Завершение работы с сокетами
        return;
    }
    else
    {
        // Используем ранее созданный порт завершения
        if(CreateIoCompletionPort((HANDLE)server_sock,hCp,0,0)==NULL)
        {
            net_error=-1;
            WSACleanup(); //Завершение работы
            return;
        }
    }
    //Заполняем структуру адреса и подключаем сокет к коммуникационной среде
    SOCKADDR_IN sinServer;
    sinServer.sin_family = AF_INET;
    sinServer.sin_port = htons(gm_PORT_SERVER);
    sinServer.sin_addr.s_addr = INADDR_ANY;
    err = bind( server_sock,(LPSOCKADDR)&sinServer,sizeof(sinServer) );
    if(err==-1)
    {
        net_error=-1;
        WSACleanup(); //Завершение работы
        return;
    }
    //Создаем очередь для ожидания запросов от клиентов на соединение
    err = listen(server_sock, SOMAXCONN);
    if(err==-1)
    {
        net_error=-1;
        WSACleanup(); // Завершение работы
        return;
    }



}

NetCompletionPort::~NetCompletionPort()
{
    WSACleanup();
}

void NetCompletionPort::Start()
{
    //Cоздаем рабочий поток для обслуживания сообщений от порта завершения
    hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ServerPool,hCp,0, &ThreadId);
    Print("СЕРВЕР запущен\n");
}



Класс коннектов

Код

// NetConnection.h: interface for the NetConnection class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_NETCONNECTION_H__71F045AA_B2BE_4DD6_83C8_2B6158FAB442__INCLUDED_)
#define AFX_NETCONNECTION_H__71F045AA_B2BE_4DD6_83C8_2B6158FAB442__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <stdio.h>
#include <Winsock2.h>
#include "NetDefine.h"

struct NetConnection  :public OVERLAPPED 
{
public:
    NetConnection();
    virtual ~NetConnection();

    int client_number;            // ═юьхЁ ъышхэЄр
    SOCKET sock_handle;            // ╤юъхЄ ъышхэЄр
    char * buffer;                // ┴єЇхЁ ёююс∙хэшщ
    enum
    {
        op_type_send,          // ╧юё√ыър
        op_type_recv           // ╧Ёшхь
    }op_type;
};

#endif // !defined(AFX_NETCONNECTION_H__71F045AA_B2BE_4DD6_83C8_2B6158FAB442__INCLUDED_)
---------------------------------------------------------------------------------------------------------------------------------------
// NetConnection.cpp: implementation of the NetConnection class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "NetConnection.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

NetConnection::NetConnection()
{

}

NetConnection::~NetConnection()
{

}



Основная программа

Код

// Макроподстановки
// NetConnection.h: interface for the NetConnection class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(NetDefine)
#define NetDefine

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define gm_MAX_MESSAGE_SIZE 128 // размер буффера сообщения
#define gm_PORT_SERVER 28912     // номер порта сервера
#define gm_MAX_CONNECTION 1000     // максимальное количество подключенных

static int ClientCount;                // Счетчик клиентов

#endif // !NetDefine 
----------------------------------------------------- MAIN ----------------------------------------------------------------
// NetDriver.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "NetCompletionPort.h"
#include "NetConnection.h"
#include "NetDefine.h"
#include <list.h>

void SendMessageNCP(SOCKET sock_handle, char *buffer, unsigned long bytes );

static list <SOCKET> ClientList;       // Список клиентов

void Print(const char * str)
{
    char buffer[128];
    strcpy(buffer,str);
    CharToOem(buffer,buffer);
    printf(buffer);
}


DWORD WINAPI ServerPool(HANDLE hp)
{
  int err;                 // Возвращяемое значение
  unsigned long bytes;     // Кол-во байтов
  unsigned long key;       // Значение, асоциированное с хендлом порта
  char buffer[128];        // Буфер для сообщений
  LPOVERLAPPED overlapped; // Структура асинхронного I/O
  HANDLE hport=hp;         // Дескриптор порта
  DWORD flags;             // Флаги ф-ции WSARecv()
  while(true) 
  {
  // Получаем информацию о завершении операции
  if(GetQueuedCompletionStatus(hport, &bytes, &key, &overlapped, INFINITE)) 
   {
     // Операция завершена успешно
     NetConnection * ncon = (NetConnection*)overlapped;
     // Определяем тип завершенной операции и выполняем соответствующие действия
     switch(ncon->op_type) 
        {
            //Завершена отправка данных
            case NetConnection::op_type_send:
                delete [] ncon->buffer;
                delete ncon;
                break;
                //Завершен приём данных
            case NetConnection::op_type_recv:
                if(!bytes) 
                {
                    //Соединение с данным клиентом закрыто
                    ClientList.remove(ncon->sock_handle);
                    closesocket(ncon->sock_handle);
                    Print("Клиент №"); printf("%d",ncon->client_number); 
                    Print(" отключился, активных клиентов "); printf("%d\n",ClientList.size()); 
                    break;
                }
                ncon->buffer[bytes]='\0';
                strcpy(buffer,"От клиента № %d получено сообщение %s\n");
                CharToOem(buffer,buffer);
                printf(buffer,ncon->client_number,ncon->buffer);

                SendMessageNCP(ncon->sock_handle, "Test",4);

                unsigned long b;
                WSABUF buf;
                buf.buf = ncon->buffer;
                buf.len = gm_MAX_MESSAGE_SIZE;   
                flags=0; //b=0;
                err=WSARecv(ncon->sock_handle, &buf, 1, &b, &flags, ncon, 0); 
                if(!err)
                {
                    Print("Ошибка функции WSARecv");
                }
                //
        }
    }
   else 
    {
        if(!overlapped)
        {
            // Ошибка с портом
            // Закрываем все сокеты, закрываем порт, очищаем список
            //for(list<SOCKET>::iterator i=ClientList.begin();i!=ClientList.end();i++)
            //{
            //    closesocket(*i);
            //}
            //ClientList.clear();
            //strcpy(buffer,"Ошибка порта № %d, сервер завершает работу\n");
            //CharToOem(buffer,buffer);
            //printf(buffer,GetLastError());
            //getch();
            //exit(0);
        }
        else 
        {
            //Закрываем соединение с клиентом
            closesocket(((NetConnection*)overlapped)->sock_handle);
            ClientList.remove(((NetConnection*)overlapped)->sock_handle);
            strcpy(buffer,"Клиент № %d отключился, активных клиентов %d\n");
            CharToOem(buffer,buffer);
            printf(buffer,((NetConnection*)overlapped)->client_number,ClientList.size());
        }
    }
  }
  return 0;
}


int main(int argc, char* argv[])
{
    NetCompletionPort * netCP = new NetCompletionPort;
    DWORD flags;             // Флаги ф-ции WSARecv
    int err;


    if (netCP ->net_error != -1 )
    {} 
    else
    {
        Print("Произошла ошибка при создании сервера!\n");
        return 0;
    }

    netCP->Start();

    ClientCount=0;

    // Вечный цикл
    while(true)
    {
        //Принимаем запрос от программы-клиента на установление связи
        SOCKADDR_IN sinClient;
        int lenClient=sizeof(sinClient);
        SOCKET client = accept(netCP->server_sock,(struct sockaddr*)&sinClient, &lenClient);
        CreateIoCompletionPort((HANDLE)client,netCP->hCp,0,0);
        // Добавили клиента в список
        ClientList.insert(ClientList.end(),client);
        
        // Создаем структуру коннекта
        NetConnection *ncon = new NetConnection;
        // теперь заполняем ее
        ncon->sock_handle = client;
        ncon->op_type = NetConnection::op_type_recv;
        ncon->buffer = new char[gm_MAX_MESSAGE_SIZE];
        ncon->hEvent = 0;
        ncon->client_number=++ClientCount;

        Print("Подключился клиент №"); printf("%d",ClientCount); printf("\n");

            
        // Вызываем функцию чтения
        unsigned long b;
        WSABUF buf;
        buf.buf = ncon->buffer;
        buf.len = gm_MAX_MESSAGE_SIZE;
        flags=0;
        err=WSARecv(ncon->sock_handle, &buf, 1, &b, &flags, ncon, 0);
        if(!err)
        {
            Print("Ошибка функции WSARecv");
            delete [] ncon->buffer;
            delete ncon;
        }

        SendMessageNCP(client, "OK",2);
    }

    delete netCP;
    
    Print("СЕРВЕР закрыт!\n");


    return 0;
}


void SendMessageNCP(SOCKET sock_handle, char *buffer, unsigned long bytes )
{
    char buf_m[128];
    NetConnection * nconSend = new NetConnection;
    nconSend->sock_handle = sock_handle;
    nconSend->op_type = NetConnection::op_type_send;
    nconSend->buffer = new char[bytes+1];
    memcpy(nconSend->buffer, buffer, bytes);
    nconSend->buffer[bytes]='\0';
    
    unsigned long b;

    WSABUF buf;
    buf.buf = nconSend->buffer;
    buf.len = bytes;

    WSASend(nconSend->sock_handle,&buf,1,&b, 0, nconSend, 0);

    

    return;
}


Присоединённый файл ( Кол-во скачиваний: 12 )
Присоединённый файл  NetDriver.rar 4,82 Kb
PM MAIL   Вверх
ptr
Дата 24.8.2007, 06:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

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



Цитата(Scorp_progr @  23.8.2007,  18:27 Найти цитируемый пост)
Как мне кажется проблема в функции SendMessageNCP() , а именно в АПИ функции WSASend() 

Правильно думаешь, проблема именно там. WSASend шестым параметром ждет WSAOVERLAPPED, а ты ей nconSend даёшь. Нужно примерно так (посмотри в MSDN):
Код

WSAOVERLAPPED SendOverlapped = {0};
SendOverlapped.hEvent = WSACreateEvent();
WSASend(nconSend->sock_handle,&buf,1,&b, 0, &SendOverlapped, 0);


Это сообщение отредактировал(а) ptr - 24.8.2007, 06:23


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
Scorp_progr
Дата 24.8.2007, 09:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



nconSend  наследуется от WSAOVERLAPPED, поэтому тут все нормально.

Я нашел причину ошибки, она было в простом не обнулении hEvent, если перед вызовом WSASend добавить :

nconSend->hEvent =  0;

тогда все заработает!
PM MAIL   Вверх
ptr
Дата 24.8.2007, 10:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

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



Лично у тебя от OVERLAPPED (правда это тот же WSAOVERLAPPED).


Цитата(Scorp_progr @  24.8.2007,  12:37 Найти цитируемый пост)
Я нашел причину ошибки, она было в простом не обнулении hEvent, если перед вызовом WSASend добавить :nconSend->hEvent =  0;

Тогда уж WSACreateEvent.


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
Scorp_progr
Дата 24.8.2007, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



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

А для чего вобще свойство hEvent может использоваться ?
PM MAIL   Вверх
ptr
Дата 27.8.2007, 06:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

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



Читай MSDN:
Цитата

hEvent 
If an overlapped I/O operation is issued without an I/O completion routine (the operation's lpCompletionRoutine parameter is set to null), then this parameter should either contain a valid handle to a WSAEVENT object or be null. If the lpCompletionRoutine parameter of the call is non-null then applications are free to use this parameter as necessary. 



--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




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


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

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