Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.83
mh-coder
24 / 23 / 3
Регистрация: 01.02.2014
Сообщений: 770
#1

Сокеты: после вызова send программа зависает на функции recv - C++

25.08.2014, 16:18. Просмотров 1859. Ответов 21
Метки нет (Все метки)

Извеняюсь за такое назание темы, но уже перепробовал 100 вариантов и постоянно выкидывает данное предупреждение, уже и не знаю что блин написать))

Проблема в следующем:
Изучаю сокеты и столкнулся с небольшой проблемой, в данном коде я соеденяюсь с локкал хостом на порту 2222 дабы , и прописую данный порт в прокси в браузере, дабы отлавливать его заголовки, проблема в следующем,
1) после использования функции send - код зависает над функцией recv и не двигается с места, немогу понять почему
2) если убрать send то всё работает нормально, но recv постоянно возвращает заголовки отправлнные в первый раз не реагируя на те сайты которые открываются в браузере в дальнёйшем.


main.cpp

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Mysock2.cpp: определяет точку входа для консольного приложения.
//
 
#include "stdafx.h"
#include "Server.h"
 
 
 
int _tmain(int argc, _TCHAR* argv[])
{
 
 
 
    char data[1000] = {NULL};
 
    Client c;
    Server b;
    b.LoadWinsoсk();
    b.CreateSocket();
 
    c.LoadWinsoсk();
    c.CreateSocket();
 
    b.Bind("127.0.0.1",2222,SOMAXCONN);
    b.Listen();
    b.Accept(c);
 
 
 
    while(true){
        c.RecvData(data,1000);  
 
    //  c.SendData(data,1000);
        cout<<c.GetError()<<"\n"<<data<<"\n";
 
 
    }
 
    return 0;
}

BaseNet.h

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#pragma once
#include <Windows.h>
#include <Winsock.h>
#pragma comment( lib, "Ws2_32.lib" )
 
 
class BaseNet
{
public:
    BaseNet(); 
    virtual ~BaseNet();
 
    bool LoadWinsoсk(void); // метод згрузки библиотеки Ws2_32.dll
    bool CreateSocket(void); // метод создания  сокета
    bool SendData(LPCSTR,const int &); // метод  передачи данных
    bool RecvData(LPSTR,const int &); // метод полученя данных
    bool CloseSocket(void); // метод закрытия сокета
    bool UnloadWinsock(void);// метод выгрузки Ws2_32.dll
    int GetError(void)const; // метод возврата кода ошибки
    int GetSendSize(void)const; //метод возврата количеств переданых байтов методом SendData
    int GetRecvSize(void)const;// метод возврата киличества принятых байтов методом vData
    
 
protected:
 
    WSADATA ws; //структура
    SOCKET Socket;
    struct sockaddr_in addr; //структура информации:ip, post, семейство протоколов
    int err; //код ошибки
    int size_send, size_recv;// количество переданных/принятых байт
 
private:
 
    bool Load_WSDATA;
};
BaseNet.cpp

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "stdafx.h"
#include "BaseNet.h"
 
 
BaseNet::BaseNet()
{
 
    memset(&this->ws, 0, sizeof(ws));
    this->Socket = NULL;
    memset(&this->addr, 0, sizeof(addr));
    this->err = 0;
    this->size_send = 0, this->size_recv = 0;
    this->Load_WSDATA = false;
}
 
 
BaseNet::~BaseNet()
{
 
    this->UnloadWinsock();
}
 
 
bool BaseNet::LoadWinsoсk(void){
 
    if (WSAStartup(0x0202, &this->ws))
    {
        this->err = WSAGetLastError();
        return false;
    }
    this->Load_WSDATA = true;
    return true;
}
 
 
bool BaseNet::CreateSocket(void){
 
    this->Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if (this->Socket == SOCKET_ERROR){
 
        this->err = WSAGetLastError();
        return false;
    }else{
        return true;
    }
 
}
 
 
bool BaseNet::SendData(LPCSTR _pbuf, const int & size_buf){
 
    this->size_send = send(this->Socket, _pbuf, size_buf, 0);
 
    if (this->size_send == SOCKET_ERROR){
 
        this->err = WSAGetLastError();
        return false;
    }
    else{
        return true;
    }
 
}
 
 
bool BaseNet::RecvData(LPSTR _pbuf, const int & size_buf){
    
 
    this->size_recv = recv(this->Socket, _pbuf, size_buf, 0);
 
    if (this->size_recv == SOCKET_ERROR){
 
        this->err = WSAGetLastError();
        return false;
    }
    else{
        return true;
    }
 
}
 
 
bool BaseNet::CloseSocket(void){
 
    if (closesocket(this->Socket) == SOCKET_ERROR){
        this->err = WSAGetLastError();
        return false;
    }
    else{
        return true;
    }
 
}
 
bool BaseNet::UnloadWinsock(void){
    if (this->Load_WSDATA){
    if (WSACleanup() == SOCKET_ERROR){
        this->err = WSAGetLastError();
        return false;
    }
    else{
        return true;
    }
}
    return false;
}
 
 
int BaseNet::GetError(void)const{
    return this->err;
}
 
 
int BaseNet::GetSendSize(void)const{
    return this->size_send;
 
}
int BaseNet::GetRecvSize(void)const{
    return this->size_recv;
}
Server.h

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#pragma once
#include "BaseNet.h"
#include "Client.h"
class Server : public BaseNet
{
public:
    Server();
    virtual ~Server();
 
    bool Bind( LPCSTR       = "127.0.0.1",  // По умолчанию IP локальный, для удобства тестирования
        const UINT& = 33333,        // По умолчанию порт 33333
        const int&  = SOMAXCONN );  // По умолчанию SOMAXCONN клиентов будет ожидать сервер
 
 
    bool Listen(void); // метод прослушивания подключения клиентов
    bool Accept(Client &); // метод приёма поключения клиента
 
    // Остановка сервера
    bool StopServer( void );
 
 
};
Server.cpp

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "stdafx.h"
#include "Server.h"
 
 
Server::Server(void)
{
}
 
 
Server::~Server(void)
{
}
 
 
bool Server::Bind(LPCSTR _ip , const UINT &_port, const int &_count_client){
 
    BaseNet::addr.sin_family        = AF_INET;
    BaseNet::addr.sin_port          = htons( _port );
    BaseNet::addr.sin_addr.s_addr   = inet_addr( _ip );
 
 
    if( bind( BaseNet::Socket, ( const sockaddr* ) &this->addr, sizeof( BaseNet::addr ) ) == SOCKET_ERROR )
 
    {
        this->err = WSAGetLastError( );
        return false;
    }else{
        return true;
    }
 
 
}
 
bool Server::Listen(void){
 
    if ( listen( BaseNet::Socket, SOMAXCONN ) == SOCKET_ERROR )
    {
        BaseNet::err = ::WSAGetLastError( );
        return false;
    }else{
        return true;
    }
 
}
 
 
bool Server::Accept(Client &_client){
 
    SOCKET client_socket    = NULL;    
    sockaddr_in client_addr = { 0 };        
    int client_addr_size    = sizeof( client_addr );
 
    client_socket           = accept(   Socket, 
        ( sockaddr* )&client_addr, 
        &client_addr_size );
 
    if( client_socket == SOCKET_ERROR )
    {
        BaseNet::err = WSAGetLastError( );
        return false;
    }
 
    _client.SaveSocketAndSockaddr( client_socket, &client_addr );
    return true;
}
 
 
// Остановка сервера
bool Server::StopServer( void )
{
    // Закрытие сокета
    if( !BaseNet::CloseSocket( ) )
        return false;
 
    // Выгрузка Winsock
    if( !BaseNet::UnloadWinsock( ) )
        return false;
 
    return true;
}
Client.h

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#pragma once
#include "BaseNet.h"
class Client : public BaseNet
{
public:
    Client(void);
    virtual ~Client(void);
 
 
    // Подключение к серверу
        bool Connect(   LPCSTR      = "127.0.0.1",  // IP/Name сервера
                        const UINT& = 33333 );      // Порт сервера
 
        // Отключение от сервера
        bool Disconnect( void );
 
        // Метод установки сохранение сокета и структуры сетевой информации
        void SaveSocketAndSockaddr( const SOCKET&,          // Сокет
                                    const sockaddr_in* );   // Структура sockaddr_in
 
};
Client.cpp

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "stdafx.h"
#include "Client.h"
 
 
Client::Client(void)
{
}
 
 
Client::~Client(void)
{
}
 
// Подключение к серверу
bool Client::Connect(   LPCSTR      _ip,        // IP/Name сервера
                        const UINT  &_port )    // Порт сервера
{
 
 
    // Заполнение структуры сетевой информации о сервере
    BaseNet::addr.sin_addr.s_addr = inet_addr( _ip );
    if( INADDR_NONE == BaseNet::addr.sin_addr.s_addr )
    {
        struct hostent *h = gethostbyname( _ip );
        if( !h )
        {
            BaseNet::err = WSAGetLastError( );
            return false;
        }
        BaseNet::addr.sin_addr = *(struct in_addr *) h->h_addr_list[0];
    }
    BaseNet::addr.sin_family    = AF_INET;
    BaseNet::addr.sin_port      = htons( _port );
 
    // Соединение с сервером
    if( connect( BaseNet::Socket, ( const struct sockaddr* )&this->addr, sizeof( BaseNet::addr ) ) == SOCKET_ERROR )
    {
        BaseNet::err = WSAGetLastError( );
        return false;
    }
    
    return true;
}
 
        
// Отключение от сервера
bool Client::Disconnect( void )
{
    // Закрытие сокета
    if( !BaseNet::CloseSocket( ) )
        return false;
 
    // Выгрузка Winsock
    if( !BaseNet::UnloadWinsock( ) )
        return false;
    
    return true;
}
 
// Метод установки сохранение сокета и структуры сетевой информации
void Client::SaveSocketAndSockaddr( const SOCKET        &_socket,   // Сокет
                                    const sockaddr_in   *_paddr )   // Структура sockaddr_in
{
    BaseNet::Socket = _socket;
    memcpy_s( &this->addr, sizeof( sockaddr_in ), _paddr, sizeof( sockaddr_in ) );
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.08.2014, 16:18     Сокеты: после вызова send программа зависает на функции recv
Посмотрите здесь:
C++ После вызова рекурсивной функции программа перестаёт работать
оформить решение в виде функции следующими способами: 1. функция расположена после ее вызова; 2. функция расположена после до ее вызова; 3. функ C++
Сокеты, функция send C++
C++ MPI зависает на Recv
Глобальная переменная после вызова функции меняет значение C++
C++ нужно чтобы функция располагалась до ее вызова, после ее вызова и в другом файле. Как это сделать?
Каким будет значение переменной k после вызова функции f в main: C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
mh-coder
24 / 23 / 3
Регистрация: 01.02.2014
Сообщений: 770
29.08.2014, 11:53  [ТС]     Сокеты: после вызова send программа зависает на функции recv #16
В общем, я сделал проверки на ошибки, постоянно когда после одного хоста сокет конектится к другому вылетает лишбка 10056, пробовал каждый раз при смене домена отключать и заново создавать сокет, но тогда он посоянно выкидывает ошибку 10093, как нужно сделать правильно?

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "stdafx.h"
#include "Header.h"
#include "Server.h"
 
DWORD WINAPI Thread( LPVOID );
 
 
 
 
int _tmain(int argc, _TCHAR* argv[])
{
 
    Array ex;
    string url,url_now;
    char data[1024*64] = {NULL};
 
    Client c2;
    Client c;
    Server b;
    b.LoadWinsoсk();
    b.CreateSocket();
 
 
 
    c.LoadWinsoсk();
    c.CreateSocket();
 
    c2.LoadWinsoсk();
    c2.CreateSocket();
 
    b.Bind("127.0.0.1",2222,SOMAXCONN);
    b.Listen();
 
 
 
    while(true){
 
        b.Accept(c);
 
 
        /*HANDLE Th = CreateThread(  NULL,NULL,Thread,(LPVOID)&c,NULL,NULL );   
        CloseHandle( Th );*/
 
        cout<<c.GetError()<<"\n"<<"\n";
 
 
 
        c.RecvData(data,sizeof(data));  
 
        ex = explode("\r\n",data);
        url = str_replace("Host: ","",ex[1] );
 
 
        //тут получаем домен
 
 
        if( url_now != url ) {
 
 
            c2.Connect(url.c_str(),80);
            cout<<"Connect - "<<c2.GetError()<<" now_url- "<<url_now<<" url - "<<url<<"\n";
            url_now = url;
        }
 
 
        c2.SendData(data,c.GetRecvSize());
        cout<<"Send hendle of browser - "<<c2.GetError()<<"\n"<<"\n";
 
 
        while(true)
        {
            c2.RecvData(data,sizeof(data));
            cout<<"Get info from site- "<<c2.GetError()<<"\n"<<"\n";
            if(c2.GetRecvSize() == 0 || c2.GetRecvSize() == SOCKET_ERROR){
                break;  
            }
            c.SendData(data,c2.GetRecvSize());
            memset(data,0,sizeof(data));
        }
        //c2.Disconnect();
    }
 
    return 0;
}
aLarman
642 / 563 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
29.08.2014, 12:00     Сокеты: после вызова send программа зависает на функции recv #17
mh-coder, я надеюсь Вы понимаете что ф-ции accept, сonnect, recv могуть быть блокирующими, и вся работа может остановится

Добавлено через 3 минуты
Цитата Сообщение от mh-coder Посмотреть сообщение
вылетает лишбка 10056
WSAEISCONN - судя по всему пишет что уже законнекчено
Цитата Сообщение от mh-coder Посмотреть сообщение
но тогда он посоянно выкидывает ошибку 10093
WSANOTINITIALISED - тут вроде понятно, но с таким не встречался, просто если вы отключаетесь и сразу коннектитесь, с этого же сокета, есть вариант, что соединение не успело порваться(tcp оно такое)
mh-coder
24 / 23 / 3
Регистрация: 01.02.2014
Сообщений: 770
29.08.2014, 12:18  [ТС]     Сокеты: после вызова send программа зависает на функции recv #18
ну а как мне тогда отключится от одного севера и подключится к другому чтобы не возникало ошибок?
aLarman
642 / 563 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
29.08.2014, 15:54     Сокеты: после вызова send программа зависает на функции recv #19
Цитата Сообщение от mh-coder Посмотреть сообщение
другому чтобы не возникало ошибок?
ну создать новый сокет для подключения...или.....ждать пока предыдущее соединение закроется
mh-coder
24 / 23 / 3
Регистрация: 01.02.2014
Сообщений: 770
29.08.2014, 22:04  [ТС]     Сокеты: после вызова send программа зависает на функции recv #20
как установить время ожидания получения данных и время подключения для сокета? читал мсдн, там херь какая-то написана)) на подобии
Socket->ReceiveTimeout = 1000;

Добавлено через 10 минут
...
aLarman
642 / 563 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
30.08.2014, 00:30     Сокеты: после вызова send программа зависает на функции recv #21
там про другие сокеты, это время вроде не выставляется(быть может что то путаю) советую почитать про мультиплексированный ввод вывод, ну или потоки....
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.08.2014, 15:08     Сокеты: после вызова send программа зависает на функции recv
Еще ссылки по теме:
Зависает программа после ввода массива C++
C++ Обработка функции recv структуры SOCKET
C++ Как избавиться от остановки программы из-за функции recv()?
Использование объекта после вызова деструктора C++
C++ Краш программы после вызова Inverse_element

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
mh-coder
24 / 23 / 3
Регистрация: 01.02.2014
Сообщений: 770
30.08.2014, 15:08  [ТС]     Сокеты: после вызова send программа зависает на функции recv #22
Цитата Сообщение от aLarman Посмотреть сообщение
1ый вариант, знать это априори
2) в конце последовательности иметь уникальную посл.байт, что бы понять что все пришло Добавлено через 33 секунды
3) в передаваемой посл.байт отвести байт задающий длину последовательности
чесно говоря я ни слова не понял из написаного, а можно написать более понятны языком?

Добавлено через 2 часа 47 минут
Вобщем вот что в конце получилось, но серовно идеально неработает, код отрабатывает, но браузер всегда подвисает на том что должно было грузится последним и несмотря на то что код уже отработал - браузер черовно ждёт ответа, хелп, неужели тут никто сокеты не знает, я не верю

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Mysock2.cpp: определяет точку входа для консольного приложения.
//
 
#include "stdafx.h"
#include "Header.h"
#include "Server.h"
 
DWORD WINAPI Thread( LPVOID );
 
struct info{
    char data[1024*64];
    Client C;
};
 
 
 
int _tmain(int argc, _TCHAR* argv[])
{
 
 
 
    Array ex;
    string url;
    char data[10240] = {NULL};
 
    Client c2;
    Client c;
    Server b;
    b.LoadWinsoсk();
    b.CreateSocket();
 
 
 
 
    c.CreateSocket();
 
 
 
 
    b.Bind("127.0.0.1",2222,SOMAXCONN);
    b.Listen();
 
    info send;
 
 
    while(true){
 
        b.Accept(c);
        
 
        if(c.GetRecvSize() != SOCKET_ERROR) {
            memset(data,0,sizeof(data));
            c.RecvData(data,sizeof(data));  
            strcpy(send.data,data);
            send.C = c;
            HANDLE Th = CreateThread(  NULL,NULL,Thread,(LPVOID)&send,NULL,NULL );   
            CloseHandle( Th );
 
        }
 
    }
 
    c.Disconnect();
    b.StopServer();
    return 0;
}
 
DWORD WINAPI Thread( LPVOID _param )
{
 
 
 
    info rec = *((info*)_param);
    Client c = rec.C;
    char data[1024*64] = {NULL};
    strcpy(data,rec.data);
 
    pFile a;
    Client c2;
    Array ex;
    string url;
    c2.LoadWinsoсk();
    c2.CreateSocket();
 
 
    if(strlen(data) == 0) {
        c2.Disconnect();
        return 0;
    }else{
        ex = explode("\r\n",data);
        url = str_replace("Host: ","",ex[1] );
        c2.Connect(url.c_str(),80);
 
 
        
        a.open("test.txt","w");
        a.write(data);
        a.write("\n\n");
 
    
        c2.SendData(data,strlen(data));
            
        //cout<<"\n--------------------------------------\n"<<data<<"\n--------------------------------------\n";
        while(true)
        {
            
 
 
            c2.RecvData(data,sizeof(data)-1);
            if(c2.GetRecvSize() == 0 || c2.GetRecvSize() == SOCKET_ERROR){
                c.SendData(data,c2.GetRecvSize());
                break;  
            }
 
    
            a.write(data);
            a.write("\n\n");
        
                
            c.SendData(data,c2.GetRecvSize());
        
 
            if(c.GetSendSize() == 0 || c.GetSendSize() == SOCKET_ERROR || data[c2.GetRecvSize()] == '\0'){
                break;  
            }
 
            memset(data,0,sizeof(data));
        }
 
 
 
    }
    a.close();
    c2.Disconnect();
    return 0;
}
Yandex
Объявления
30.08.2014, 15:08     Сокеты: после вызова send программа зависает на функции recv
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru