Вопрос : проблемы при работе сервера по Tcp/ip (Сокеты)

Тема в разделе "MS Visual C++", создана пользователем 4xter, 17 ноя 2010.

  1. 4xter

    4xter Гость

    Народ, всем доброго дня=) такая проблемка имеется сервак, к которому подключаются клиенты и который обрабатывает набор данных и отправляет клиенту. Так вот всё отрабатывает правильно и рассчитывает всё здорово, но вот сервак постоянно идет по циклу считывания данных с сокета и причем постоянно. В чем беда не могу понять. Очень надеюсь на вашу помощь.
    Вот код серкера. Он получает 2 координаты и возвращает номер четверти, в которой расположена точка:
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"Сервер"</div></div><div class="sp-body"><div class="sp-content">#include <winsock2.h>
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>

    using namespace std;
    int main()
    {
    WORD wVersionRequested;
    WSADATA wsaData;
    wVersionRequested=MAKEWORD(2,2);
    WSAStartup(wVersionRequested,&wsaData);//инициализация WinSock API
    //Создание сокета
    SOCKET s=socket(AF_INET,SOCK_STREAM,0);
    //структура адреса
    struct sockaddr_in local;
    local.sin_family=AF_INET;
    local.sin_port=htons(1280);
    local.sin_addr.s_addr=htons(INADDR_ANY); //хранится физический IP
    int c=bind(s,(struct sockaddr*)&local,sizeof(local));
    //помещает сокет в состояние прослушивания
    int r=listen(s,5);
    while (true)
    {
    char b1[255];
    //b1 = (char*)malloc(strlen(b1) + 1);
    char *b2,*Res,*token,*tmp;
    int x,y;
    b2 = (char*)malloc(strlen(b1) + 1);
    //free(b2);
    //Структура определяет удаленный адрес
    //с которым соединяется сокет
    sockaddr_in remote_addr;
    int size=sizeof(remote_addr);
    SOCKET s2=accept(s,(struct sockaddr*)&remote_addr,&size);
    if (s2 == INVALID_SOCKET)
    continue;
    cout << "Client connected..." << endl;

    while(recv(s2,b1,sizeof(b1),0)!=0)
    {
    int mas[2],x,y,n=0,res=0;
    char cset[] = "1234567890-";
    //Разбитие на координаты.
    tmp=new char[strlen(b1)];
    strcpy(tmp,b1);
    token = strtok(tmp,";");
    while( token != NULL )
    {
    int fl=0;
    char * pch = token;
    if (pch[0]=='-')
    fl=1;
    while(!isdigit(*pch))
    {pch++;}
    if (pch!=NULL)
    {
    if (fl==0)
    mas[n]=atoi(pch);
    else
    mas[n]=atoi(pch)*(-1);
    n++;
    }
    token = strtok( NULL,";");
    }
    x=mas[0];
    y=mas[1];
    if ((x>0)&&(y>0))
    res=1;
    else if ((x<0)&& (y>0))
    res=2;
    else if ((x<0)&& (y<0))
    res=3;
    else if ((x>0)&& (y<0))
    res=4;
    _itoa(res,b2,10);
    Res=new char[strlen(b2)+1];
    strcpy(Res,b2);
    Res[strlen(b2)]='\0';
    send(s2,Res,sizeof(Res),0);
    cout << "Message sent"<< endl;
    }
    closesocket(s2);
    //delete []Res;
    //free(b1);
    }

    WSACleanup();
    return 0;
    }
     
  2. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Ты имеешь в виду что он никогда не выходит из этого цикла?
    Код (C++):
    while(recv(s2,b1,sizeof(b1),0)!=0)
     
  3. 4xter

    4xter Гость

  4. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    If no incoming data is available at the socket, the recv call blocks and waits for data to arrive according to the blocking rules defined for WSARecv with the MSG_PARTIAL flag not set unless the socket is nonblocking.

    Понимаешь в чем смысл?

    Добавлено: Посмотри вот здесь и описание и пример есть:
    http://msdn.microsoft.com/en-us/library/ms...28VS.85%29.aspx
     
  5. 4xter

    4xter Гость

    как я понял нужно заблокировать сокет, так?
    но у меня не получилось закрыть его. я взял closesocket(s2); перенёс в конец цикла.
     
  6. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    4xter
    Да нет. Я другое имел в виду. Функция recv() не возвращается до тех пор, пока не прочитает что-то из сокета. А когда она что-то прочитывает то возвращаешь значение > 0, т.е. количество прочитанных байт и, соответственно, цикл крутится. Он может прерваться только в том случае если возникнет какая-то ошибка но они, как я понял не возникают. Думаю что все дело в этом. На 100% утверждать конечно не буду, это просто мое предположение.
     
  7. 4xter

    4xter Гость

    я как-то вообще запутался...вот кусок кода с другой задачи сервера, которая возвращает слово в обратном порядке:
    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"Сервер2"</div></div><div class="sp-body"><div class="sp-content">while(recv(s2,b1,sizeof(b1),0)!=0)
    {
    cout << b1 << endl;
    int i=strlen(b1);
    b2=b1[strlen(b1)];//копируем окончание стоки
    i--;
    cout <<strlen(b1)<<endl;
    for(unsigned j=0;j<=strlen(b1);j++)

    {
    if (i>=0)
    {
    b2=b1[j];
    i--;
    }
    }
    for(unsigned j=0;j<=strlen(b1);j++)
    b1[j]=b2[j];
    send(s2,b1,sizeof(b1),0);
    cout << "Message sent"<< endl;
    }

    Подключение к сокету один в один как в предыдущем. Здесь всё Ок и никаких подвисаний не наблюдается. В чём может быть проблема?!
     
  8. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Можешь выложить второй сервер целиком?
     
  9. 4xter

    4xter Гость

    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"Сервер2 "</div></div><div class="sp-body"><div class="sp-content">#include <winsock2.h>
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>

    using namespace std;
    int main()
    {
    WORD wVersionRequested;
    WSADATA wsaData;
    wVersionRequested=MAKEWORD(2,2);
    WSAStartup(wVersionRequested,&wsaData);//инициализация WinSock API
    //Создание сокета
    SOCKET s=socket(AF_INET,SOCK_STREAM,0);
    //структура адреса
    struct sockaddr_in local;
    local.sin_family=AF_INET;
    local.sin_port=htons(1280);
    local.sin_addr.s_addr=htons(INADDR_ANY); //хранится физический IP
    int c=bind(s,(struct sockaddr*)&local,sizeof(local));
    //помещает сокет в состояние прослушивания
    int r=listen(s,5);
    while (true)
    {
    char b1[128];
    //b1 = (char*)malloc(strlen(b1) + 1);
    char *b2;
    b2 = (char*)malloc(strlen(b1) + 1);
    //free(b2);
    //Структура определяет удаленный адрес
    //с которым соединяется сокет
    sockaddr_in remote_addr;
    int size=sizeof(remote_addr);
    SOCKET s2=accept(s,(struct sockaddr*)&remote_addr,&size);
    if (s2 == INVALID_SOCKET)
    continue;
    cout << "Client connected..." << endl;

    while(recv(s2,b1,sizeof(b1),0)!=0)
    {
    cout << b1 << endl;
    int i=strlen(b1);
    b2=b1[strlen(b1)];//копируем окончание стоки
    i--;
    cout <<strlen(b1)<<endl;
    for(unsigned j=0;j<=strlen(b1);j++)

    {
    if (i>=0)
    {
    b2=b1[j];
    i--;
    }
    }
    for(unsigned j=0;j<=strlen(b1);j++)
    b1[j]=b2[j];
    send(s2,b1,sizeof(b1),0);
    cout << "Message sent"<< endl;
    }
    closesocket(s2);
    }

    WSACleanup();
    return 0;
    }
     
  10. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Начну пожалуй вот с чего:
    Код (C++):
    while (true)
    {
    char b1[128];
    //b1 = (char*)malloc(strlen(b1) + 1);
    char *b2;
    b2 = (char*)malloc(strlen(b1) + 1);
    Ты выделяешь память для b2 определяя размер строки b1 которая ни разу не инициализировалась! Т.е. память под b2 может вообще не выделится.

    Вот тут тоже какая то странная конструкция:
    Код (C++):
    int i=strlen(b1);
    b2[i]=b1[strlen(b1)];//копируем окончание стоки
    Почему бы вторую строку не заменить на: b2=b1; ?

    И это я только сразу заметил. Ты бы сначала все ошибки исправил а потом бы мы уже подумали что, почему и как не работает.
     
  11. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    И еще. Когда постишь код вставляй его в тэг C++.
     
  12. 4xter

    4xter Гость

    мне нужна помощь в выходе из цикла чтения сокета, а не выделения памяти и алгоритма работы сервера... я понимаю что есть ошибки и т.д. но как они влияют на чтение?
     
  13. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Андрей я с Вас фигею.. Возникает ошибка - из-за этого прерывается выполнение recv() а так же прерывается цикл и вы начинаете думать что все работает как надо хотя на самом деле все далеко не так. В общем правьте ошибки.
     
  14. 4xter

    4xter Гость



    по порядку что поправил: память под b2 выделяется. переменная i мне нужна как обратный счетчик для формирования строки-зеркала. пусть поменяется b2=b1[strlen(b1)] на b2=b1. я так понял что в коде сервер2 где возникает ошибка в b1? так это? Не судите строго, только начинаю всё это осваивать!=)
     
  15. 4xter

    4xter Гость

    код клиента выслал
     
  16. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Сейчас немного занят на работе. Посмотрю ближе к вечеру.

    Добавлено: 4xter
    В клиенте, который ты мне прислал есть строки подобные вот этой:
    Код (C++):
    if ( recv( s, b, sizeof( cool.gif, 0 ) != 0 ) {
    Думаю там какой-то символ был распознан как смайл.
    Не подскажешь что там должно быть? Или как вариант можно прислать еще раз но только в аську.
     
  17. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Вот тебе сервер:
    Код (C++):
    #include <winsock2.h>
    #include <iostream.h>

    int main( void )
    {
    WORD        wVersionRequested;
    WSADATA     wsaData;

    wVersionRequested = MAKEWORD( 2, 2 );
    if ( WSAStartup( wVersionRequested, &wsaData ) != 0 ) {
    cout << "WSAStartup(): error" << endl;
    return 1;
    }

    SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );

    struct sockaddr_in  local;
    local.sin_family        = AF_INET;
    local.sin_port          = htons( 1280 );
    local.sin_addr.s_addr   = htons( INADDR_ANY );

    bind( s, (struct sockaddr *)&local, sizeof( local ) );
    listen( s, 5 );
    while ( 1 ) {
    int         size, xy[2], z;
    SOCKET      s2;
    sockaddr_in remote_addr;

    size = sizeof( remote_addr );

    s2 = accept( s, (struct sockaddr *)&remote_addr, &size );
    if ( s2 == INVALID_SOCKET ) continue;

    cout << "Client connected..." << endl;

    while ( recv( s2, (char *)&xy[0], sizeof( int ) * 2, 0 ) != 0 ) {
    cout << "Server received: X = " << xy[0] << ", Y = " << xy[1] << endl;
    cout.flush();

    z = xy[0] * xy[1];  // Schitaem proizvedenie

    send( s2, (char *)&z, sizeof( int ), 0 );
    }
    closesocket( s2 );
    }
    WSACleanup();
    return 0;
    }
    А вот тебе клиент:
    Код (C++):
    #include <winsock2.h>
    #include <iostream.h>

    int main( void )
    {
    WORD        wVersionRequested;
    WSADATA     wsaData;

    wVersionRequested = MAKEWORD( 2, 2 );
    if ( WSAStartup( wVersionRequested, &wsaData ) != 0 ) {
    cout << "WSAStartup(): error" << endl;
    return 1;
    }

    sockaddr_in     peer;
    peer.sin_family         = AF_INET;
    peer.sin_port           = htons( 1280 );
    peer.sin_addr.s_addr    = inet_addr( "127.0.0.1" );

    SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );
    if ( connect( s, (struct sockaddr *)&peer, sizeof( peer ) ) != 0 ) {
    cout << "connect(): error" << endl;
    return 1;
    }

    int     xy[2], z;
    cout << "Enter X: ", cin >> xy[0];
    cout << "Enter Y: ", cin >> xy[1];

    send( s, (char *)&xy, sizeof( int ) * 2, 0 );
    if ( recv( s, (char *)&z, sizeof( int ), 0 ) != 0 ) {
    cout << "Server returns: " << z << endl;
    }

    closesocket( s );
    WSACleanup();
    return 0;
    }
    Сервер получает два числа от клиента и отправляет их произведение обратно клиенту. Заменишь на свою функцию и будет тебе радость.
     
  18. 4xter

    4xter Гость

    спасибо!!! переработал под свою задачу всё заработало=) по аналогии решил и со строками=)
     
  19. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Ну и славненько:ya_lamo:
     
Загрузка...
Похожие Темы - Вопрос проблемы при
  1. Генералл
    Ответов:
    2
    Просмотров:
    68
  2. ApplePen
    Ответов:
    0
    Просмотров:
    76
  3. gURaBA_N
    Ответов:
    3
    Просмотров:
    94
  4. ghost
    Ответов:
    1
    Просмотров:
    89
  5. kartaman
    Ответов:
    0
    Просмотров:
    128

Поделиться этой страницей