Re[2]: Сокеты vs Пайпы
От: Аноним  
Дата: 22.08.07 05:49
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Код покажи


Сервер и клиент работают с сокетами через один и тот же класс.
Метод инициализации сокетов одинаковый для клиента и сервера:


WSADATA wsadata;
           void Initialize()
           {
        if(WSAStartup(MAKEWORD(2,2),&wsadata)){
            throw new СIOException(WSAGetLastError());
        }
        mMainSocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if(mMainSocket==INVALID_SOCKET){
            throw new СIOException(WSAGetLastError());
        }

        bool opt = true;
        if(::setsockopt(mMainSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt))==SOCKET_ERROR){
            throw new СIOException(WSAGetLastError());
        }

        BOOL noDelay=TRUE;
        if(::setsockopt(mMainSocket, IPPROTO_TCP, TCP_NODELAY, (char *)&noDelay, sizeof(BOOL))==SOCKET_ERROR){
            throw new СIOException(WSAGetLastError());
        }    
            }


Дальше инициализация идет для сервера:

       void Listen()
           {
        SOCKADDR_IN addr;
        addr.sin_family=AF_INET;
        addr.sin_addr.s_addr=inet_addr("192.168.1.3");
        addr.sin_port=htons(33657);

        if(bind(mMainSocket,(sockaddr*)&addr,sizeof(addr))==SOCKET_ERROR){
            throw new СIOException(WSAGetLastError());
        }

        if(listen(mMainSocket, SOMAXCONN)==SOCKET_ERROR){
            throw new СIOException(WSAGetLastError());
        }

        SOCKADDR tmpAddr;
        int len = sizeof(tmpAddr);

        mActiveSocket=accept(mMainSocket,(sockaddr*)&tmpAddr,(int*)&len);
        if(mActiveSocket==INVALID_SOCKET){
            throw new СIOException(WSAGetLastError());

             }
            }


И для клиента:

            void Send()
            {
        SOCKADDR_IN addr;
        addr.sin_family=AF_INET;
        addr.sin_addr.s_addr=inet_addr("192.168.1.3");
        addr.sin_port=htons(33657);

        mActiveSocket=mMainSocket;
        if(connect(mActiveSocket,(sockaddr*)&addr,sizeof(addr))==SOCKET_ERROR){
            throw new СIOException(WSAGetLastError());
        }
            }


и два метода чтения и записи:


    CData Read()
    {
        CData data;
        if(mActiveSocket){
                        
                        // получаем размер пакета
            ULONG dataLen=0;
            int rcvLen=recv(mActiveSocket, (char*)&dataLen, sizeof(ULONG), 0);
            if(rcvLen==0){
                throw new CIOException("Соединение разорвано()");
            }else if(rcvLen==SOCKET_ERROR){
                    throw new CIOException(WSAGetLastError());
                }

                        //выделям память под пакет
                        data.AllocData(dataLen)
            char* dataAddr=data.GetDataAddr();

                        // принимаем пакет
            while(dataLen>0){
                rcvLen=recv(mActiveSocket, dataAddr, dataLen, 0);
                if(rcvLen==0){
                              throw new СIOException(WSAGetLastError());
                }else if(rcvLen==SOCKET_ERROR){
                          throw new СIOException(WSAGetLastError());
                }
                dataAddr+=rcvLen;
                dataLen-=rcvLen;
            }
        }
        return data;
    };

         void Write(CData& data)
    {
        if(mActiveSocket){
                          
                        // передаем размер пакета
            ULONG size=data.GetDataSize();    
            if(send(mActiveSocket,(char*)&size,sizeof(ULONG),0)==SOCKET_ERROR){
                      throw new СIOException(WSAGetLastError());
            }            
            char* dataAddr=data.GetDataAddr();
            ULONG  dataSize=data.GetDataSize();

                        // передаем пакет
            while(dataSize>0){
                int sentLen=0;
                if((sentLen=send(mActiveSocket,dataAddr,dataSize,0))==SOCKET_ERROR){
                                throw new СIOException(WSAGetLastError());
                }
                dataSize-=sentLen;
                dataAddr+=sentLen;
            }
        }
    };




ну и собственно основной код для сервера и клиента:


void ClientCore(СIOCtrl* cio)
{
    try
    {
        cio->Initialize();
        cio->Send();
        
        SendRain(cio,100,1000);
        SendRain(cio,1000,1000);

        cio->Write(_stopFlag);
        cio->CloseConnection();
        cio->ShutDown();
    }
    catch (CIOException* e)
    {
        cio->ShutDown();
        delete e;
    }
}

void SendRain(СIOCtrl* cio,ULONG size,int iterations)
{
    CData data;
    data.AllocData(size);

    DWORD ticks=::GetTickCount();
    int i;
    for(i=0; i < iterations; i++){
        cio->Write(data);
        if(vio->Read()!=size){
            echo("Ошибка при передаче данных");
            break;
        }
    }

    ticks=::GetTickCount()-ticks;
    printf("Передано %d блоков данных по %d байт за %d мс\r\n",i,size,ticks);
}


void ServerCore(СIOCtrl* cio)
{
    try
    {
        cio->Initialize();
        cio->Listen();

                   while(true){
            CData data=cio->Read();
            
            if(data ==_stopFlag){
                echo("Режим завершен успешно.");
                                break;
            }else{
                                CData size=data.GetDataSize();
                cio->Write(size);
            }
        }
        cio->ShutDown();
    }
    catch (CIOException* e)
    {
        cio->ShutDown();
        delete e;    
    }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.