Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.94/50: Рейтинг темы: голосов - 50, средняя оценка - 4.94
5 / 4 / 1
Регистрация: 16.08.2013
Сообщений: 110

на accept() зависает

11.12.2013, 16:06. Показов 10442. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток, делаю чат на основе win socket в консольном варианте всё работает, делаю в оконном интерфейсе зависает на accept(). Помогите кто может
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
11.12.2013, 16:06
Ответы с готовыми решениями:

Зависает accept windows forms
Как сделать что бы не зависало на accept или на другом зависает сам не пойму попробуйте сами протестировать давно не пойму #define...

После Socket.Accept() зависает приложение
После строки Socket.Accept() зависает приложение ,я знаю что этот метод останавливает выполнение кода пока он не выполнится ,как сделать...

accept
DWORD WINAPI ThreadNetworkAdminSystem(StructurNetworkAdminData &data) { StructurClientData *TmpClientData=new StructurClientData; ...

25
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,454
11.12.2013, 17:15
вы же понимаете, что функция accept придумана не вчера? и она работает. и работает как надо. она просто не может зависать. если она зависает у вас значит дело не в ней. нужно показать код.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
11.12.2013, 18:04
Цитата Сообщение от PanKiller Посмотреть сообщение
Доброго времени суток, делаю чат на основе win socket в консольном варианте всё работает, делаю в оконном интерфейсе зависает на accept().
То, что зависает - это нормально.

accept function (MSDN)
http://msdn.microsoft.com/en-u... s.85).aspx
The accept function can block the caller until a connection is present if no pending
connections are present on the queue, and the socket is marked as blocking.
Чтобы не зависало, нужно или использовать AcceptEx, или звать accept в
отдельном потоке.
1
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,454
11.12.2013, 18:10
Цитата Сообщение от Убежденный Посмотреть сообщение
То, что зависает - это нормально.
знаете, даже не смешно. давайте не путать терминологию. с тем же успехом я могу сказать, что функция синуса зависает и это нормально.
Цитата Сообщение от Убежденный Посмотреть сообщение
Чтобы не зависало, нужно или использовать AcceptEx, или звать accept в
отдельном потоке.
или не морочить себе голову и перед принятием соединения проверить есть ли собственно входящие соединения.
C++
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
    printf("wait for client...");
 
    int select_res = 0;
    while (true)
    {
        fd_set s_set;
        FD_ZERO(&s_set);
        FD_SET(s, &s_set);
        timeval timeout = {0, 0};
        select_res = select(s + 1, &s_set, 0, 0, &timeout);
        if (select_res) break;
 
        Sleep(250);
    }
    if (select_res == SOCKET_ERROR)
    {
        printf("select error\n");
        system("pause");
        return -1;
    }
 
    SOCKET ns;
 
    SOCKADDR_IN nsa;
    int sizeof_nsa = sizeof(nsa);
 
    ns = accept(s, (SOCKADDR *)&nsa, &sizeof_nsa);
    if (ns == INVALID_SOCKET)
    {
        printf("accept error\n");
        system("pause");
        return -1;
    }
1
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
11.12.2013, 18:19
Цитата Сообщение от vxg Посмотреть сообщение
знаете, даже не смешно. давайте не путать терминологию. с тем же успехом я могу сказать, что функция синуса зависает и это нормально.
Ну ок, не зависает, а блокируется. Это что-то меняет принципиально ?
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,454
11.12.2013, 18:23
Цитата Сообщение от Убежденный Посмотреть сообщение
Это что-то меняет принципиально ?
в самую точку. меняет мировоззрение. причем кардинально) сравните ответы на возглас "эта *** функция висит!!!":
1 "да, она такая, погрузите себя с разбегу в атомную асинхронность и термоядерную многопоточность"
2.1 "висение оно бывает разное"
2.2 "не используйте дрель для забивания гвоздей"
1
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
11.12.2013, 18:46
Мой вариант:

1. accept - для простых сценариев. Если нужна эффективность и хороший отклик,
следует использовать AcceptEx / многопоточность. Я бы еще сюда IOCP прикрутил.

2.1 "висение бывает разное".

2.2 "не используйте дрель для забивания гвоздей, микроскоп для этого подходит куда лучше".
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,454
11.12.2013, 19:17
конечно, к хорошему надо привыкать, но это издевательство советовать человеку, знания которого, если судить по вопросу, не позволяют свободно оперировать методиками способными дать "эффективность и хороший отклик" все эти штукенции. тем более, что в задаче которую решает этот человек (и все остальные 99,5 % разработчиков) отличия в производительности простой реализации от самой продвинутой будут "пшик да ничего"
0
5 / 4 / 1
Регистрация: 16.08.2013
Сообщений: 110
12.12.2013, 19:37  [ТС]
пожалуйста приведите пример асинхронного сервера
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
12.12.2013, 20:06
Вот сэмплы из Windows 7 SDK (overlap и iocp) - winsock.zip
Там есть все, что нужно для быстрого "въезжания" в тему.

Вот код примера, взятый из документации к AcceptEx (MSDN):
Кликните здесь для просмотра всего текста

C
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#ifndef UNICODE
#define UNICODE
#endif
 
#define WIN32_LEAN_AND_MEAN
 
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>
#include <stdio.h>
 
// Need to link with Ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
 
int main()
{
    //----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult = 0;
    BOOL bRetVal = FALSE;
 
    HANDLE hCompPort;
    HANDLE hCompPort2;
    
    LPFN_ACCEPTEX lpfnAcceptEx = NULL;
    GUID GuidAcceptEx = WSAID_ACCEPTEX;
    WSAOVERLAPPED olOverlap;
 
    SOCKET ListenSocket = INVALID_SOCKET;
    SOCKET AcceptSocket = INVALID_SOCKET;
    sockaddr_in service;
    char lpOutputBuf[1024];
    int outBufLen = 1024;
    DWORD dwBytes;
 
    hostent *thisHost;
    char *ip;
    u_short port;
 
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"Error at WSAStartup\n");
        return 1;
    }    
 
    // Create a handle for the completion port
    hCompPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (u_long) 0, 0);
    if (hCompPort == NULL) {
        wprintf(L"CreateIoCompletionPort failed with error: %u\n",
            GetLastError() );
        WSACleanup();
        return 1;
    }
            
    // Create a listening socket
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        wprintf(L"Create of ListenSocket socket failed with error: %u\n",
            WSAGetLastError() );
        WSACleanup();
        return 1;
    }
 
    // Associate the listening socket with the completion port
    CreateIoCompletionPort((HANDLE) ListenSocket, hCompPort, (u_long) 0, 0);
 
    //----------------------------------------
    // Bind the listening socket to the local IP address
    // and port 27015
    port = 27015;
    thisHost = gethostbyname("");
    ip = inet_ntoa(*(struct in_addr *) *thisHost->h_addr_list);
 
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = inet_addr(ip);
    service.sin_port = htons(port);
 
    if (bind(ListenSocket, (SOCKADDR *) & service, sizeof (service)) == SOCKET_ERROR) {
        wprintf(L"bind failed with error: %u\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
 
    //----------------------------------------
    // Start listening on the listening socket
    iResult = listen(ListenSocket, 100);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"listen failed with error: %u\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
 
    wprintf(L"Listening on address: %s:%d\n", ip, port);
 
    // Load the AcceptEx function into memory using WSAIoctl.
    // The WSAIoctl function is an extension of the ioctlsocket()
    // function that can use overlapped I/O. The function's 3rd
    // through 6th parameters are input and output buffers where
    // we pass the pointer to our AcceptEx function. This is used
    // so that we can call the AcceptEx function directly, rather
    // than refer to the Mswsock.lib library.
    iResult = WSAIoctl(ListenSocket, SIO_GET_EXTENSION_FUNCTION_POINTER,
             &GuidAcceptEx, sizeof (GuidAcceptEx), 
             &lpfnAcceptEx, sizeof (lpfnAcceptEx), 
             &dwBytes, NULL, NULL);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"WSAIoctl failed with error: %u\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
 
    // Create an accepting socket
    AcceptSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (AcceptSocket == INVALID_SOCKET) {
        wprintf(L"Create accept socket failed with error: %u\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
 
    // Empty our overlapped structure and accept connections.
    memset(&olOverlap, 0, sizeof (olOverlap));
 
    bRetVal = lpfnAcceptEx(ListenSocket, AcceptSocket, lpOutputBuf,
                 outBufLen - ((sizeof (sockaddr_in) + 16) * 2),
                 sizeof (sockaddr_in) + 16, sizeof (sockaddr_in) + 16, 
                 &dwBytes, &olOverlap);
    if (bRetVal == FALSE) {
        wprintf(L"AcceptEx failed with error: %u\n", WSAGetLastError());
        closesocket(AcceptSocket);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
 
    // Associate the accept socket with the completion port
    hCompPort2 = CreateIoCompletionPort((HANDLE) AcceptSocket, hCompPort, (u_long) 0, 0); 
    // hCompPort2 should be hCompPort if this succeeds
    if (hCompPort2 == NULL) {
        wprintf(L"CreateIoCompletionPort associate failed with error: %u\n",
            GetLastError() );
        closesocket(AcceptSocket);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    
    // Continue on to use send, recv, TransmitFile(), etc.,.
    //...
 
    return 0;
}


А здесь простейший асинхронный TCP-сервер с использованием Boost.Asio:
http://www.boost.org/doc/libs/... 3/src.html

Очень рекомендую прочесть (хотя бы "по диагонали") документацию по WinSock в MSDN, а
также найти где-нибудь книгу "Программирование в сетях Windows", т.к. там многие вопросы
сетевого программирования, в том числе касающиеся асинхронного I/O и портов завершения,
довольно хорошо разжеваны.
1
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,454
12.12.2013, 20:14
Цитата Сообщение от PanKiller Посмотреть сообщение
пожалуйста приведите пример асинхронного сервера
пожалуйста приведите пример той задачи которую вы хотите решить. указанный выше (указанный мной - прим. переводчика ) пример ожидания входящего подключения можно назвать интерактивным и неблокирующим - если это консоль: как сверхбыстрый вариант воткните в цикл функцию проверки нажатия клавиши и вы всегда сможете выйти из сервера.

Добавлено через 7 минут
Цитата Сообщение от Убежденный Посмотреть сообщение
Там есть все
с windows-адаптациями сокетов не работал, может глупое спрошу, но в примере overlap в функции DoWait Они вызывают WSAWaitForMultipleEvents с параметром WSA_INFINITE после чего, в моем понимании, этот велосипед окажется ничем не отличающимся от блокирующего accept
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
12.12.2013, 20:28
Цитата Сообщение от vxg Посмотреть сообщение
в примере overlap в функции DoWait Они вызывают WSAWaitForMultipleEvents с параметром WSA_INFINITE после чего, в моем понимании, этот велосипед окажется ничем не отличающимся от блокирующего accept
Это не так.
WSAWaitForMultipleEvents в данном примере ожидает сразу несколько операций -
как приема новых соединений, так и завершения чтения или записи на сокетах.

Но под определенной нагрузкой этот код в плане производительности очень
недалеко ушел от блокирующего accept. Да и в Windows есть ограничение на
количество объектов, на которых можно ждать - это 64.
Максимальная эффективность достигается использованием пула потоков и портов
завершения ввода-вывода, под Windows это самая выгодная модель I/O, кстати, не
только для сокетов, но и для практически любого другого I/O.
0
5 / 4 / 1
Регистрация: 16.08.2013
Сообщений: 110
12.12.2013, 22:10  [ТС]
C++
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
 WORD SERVERwVersionRequested;
    WSADATA SERVERwsaData;
    sockaddr_in SERVERaddr, SERVERCliAddr;
    SOCKET SERVERsServ, SERVERsConnSock;
    char str[255] = "";
 
void main(){
    unsigned long ul = 1;
 
 
    SERVERwVersionRequested = MAKEWORD(1,1);
    WSAStartup(SERVERwVersionRequested, &SERVERwsaData);
    SERVERsServ = socket(AF_INET,SOCK_STREAM, 0);
    ioctlsocket(SERVERsServ, FIONBIO,(unsigned long *)&ul);
 
    fd_set fdread;
    
 
    SERVERaddr.sin_family = AF_INET;
    SERVERaddr.sin_port = htons(5000);
    SERVERaddr.sin_addr.s_addr = htonl(INADDR_ANY);
 
    bind(SERVERsServ, (LPSOCKADDR)&SERVERaddr, sizeof(SERVERaddr));
    listen(SERVERsServ,2);
 
    select(0, &fdread,NULL,NULL,NULL);
    int SERVERaddrLen = sizeof(sockaddr);
    SERVERsConnSock = accept(SERVERsServ, (LPSOCKADDR)&SERVERCliAddr, &SERVERaddrLen);
while(1)
    {   
        FD_ZERO(&fdread);
        
        if(FD_ISSET(SERVERsServ,&fdread))
        {
            recv(SERVERsConnSock, (char*)&str, sizeof(str), 0);
            cout<<str;
        }
    }
 
 
 
    closesocket(SERVERsServ);
    WSACleanup();
    _getch();
}
Добавлено через 1 минуту
это как бы намёк на то что должно получиться, это серверная часть в асинхронном режиме, правда куда пихать функцию select вообще не пойму, поглядите плиз...
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,454
13.12.2013, 07:05
Цитата Сообщение от Убежденный Посмотреть сообщение
Это не так
еще раз поправьте если я ошибаюсь, но это так. функция WSAWaitForMultipleEvents может ждать сколько угодно событий каких угодно типов, но, поскольку она вызвана с бесконечным таймаутом, это, в рассматриваемом случае, эквивалентно останову выполнения программы до момента приема подключения. что ничем не отличается от accept. опережая разъяснения: вызов WSAWaitForMultipleEvents с конечным таймаутом на мой взгляд ничем не отличается от вызова select. хотя нет. отличается непереносимостью на другие платформы.
Цитата Сообщение от PanKiller Посмотреть сообщение
это как бы намёк на то что должно получиться
select должен быть между FD_ZERO и FD_ISSET. для обострения понимания полный код серверной консоли принимающей файл (кусок был приведен выше, но целиком, наверное, будет лучше для восприятия)
C++
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <winsock>
#include <stdio.h>
 
int main(int argc, char* argv[])
{
    int server_port = 5500;
    char *file_name = "test.txt";
    int part_size = 1024;
 
    WSADATA wsa_data;
    if (WSAStartup(0x101, &wsa_data))
    {
        printf("WSAStartup error\n");
        system("pause");
        return -1;
    }
    if (wsa_data.wVersion != 0x101)
    {
        printf("WSA version error\n");
        system("pause");
        return -1;
    }
 
    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s == INVALID_SOCKET)
    {
        printf("socket error\n");
        system("pause");
        return -1;
    }
 
    SOCKADDR_IN sa;
    sa.sin_family = AF_INET;
    sa.sin_port = htons(server_port);
    sa.sin_addr.S_un.S_addr = INADDR_ANY;
 
    if (bind(s, (SOCKADDR *)&sa, sizeof(sa)) == SOCKET_ERROR)
    {
        printf("bind error\n");
        system("pause");
        return -1;
    }
    if (listen(s, SOMAXCONN) == SOCKET_ERROR)
    {
        printf("listen error\n");
        system("pause");
        return -1;
    }
 
    printf("wait for client...");
 
    int select_res = 0;
    while (true)
    {
        fd_set s_set;
        FD_ZERO(&s_set);
        FD_SET(s, &s_set);
        timeval timeout = {0, 0};
        select_res = select(s + 1, &s_set, 0, 0, &timeout);
        if (select_res) break;
 
        Sleep(250);
    }
    if (select_res == SOCKET_ERROR)
    {
        printf("select error\n");
        system("pause");
        return -1;
    }
 
    SOCKET ns;
 
    SOCKADDR_IN nsa;
    int sizeof_nsa = sizeof(nsa);
 
    ns = accept(s, (SOCKADDR *)&nsa, &sizeof_nsa);
    if (ns == INVALID_SOCKET)
    {
        printf("accept error\n");
        system("pause");
        return -1;
    }
 
    printf("connected\n");
 
    printf("transfer...");
 
    FILE *f = fopen(file_name, "wb");
    if (!f)
    {
        printf("fopen error\n");
        system("pause");
        return -1;
    }
 
    long file_size = 0;
 
    if (recv(ns, (char *)&file_size, sizeof(file_size), 0) != sizeof(file_size))
    {
        printf("recv error\n");
        system("pause");
        return -1;
    }
 
    char *buffer = new char[part_size];
 
    while (file_size)
    {
        int n = recv(ns, buffer, part_size, 0);
        if (!n)
        {
            printf("disconnected\n");
            system("pause");
            return -1;
        }
        if (n == SOCKET_ERROR)
        {
            printf("recv error\n");
            system("pause");
            return -1;
        }
        file_size -= n;
        if (file_size < 0)
        {
            printf("file_size error\n");
            system("pause");
            return -1;
        }
        if (fwrite(buffer, 1, n, f) != n)
        {
            printf("fwrite error\n");
            system("pause");
            return -1;
        }
    }
 
    delete [] buffer;
 
    fclose(f);
 
    closesocket(ns);
 
    closesocket(s);
 
    printf("complete\n");
 
    WSACleanup();
 
    system("pause");
    return 0;
}
Добавлено через 3 минуты
если возникнет вопрос - почему в примере нет FD_ISSET: потому что сокет в наборе один и нет необходимости проверять что установлен именно он: если в наборе установлен хоть один сокет, то это может быть только он
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
13.12.2013, 11:43
Цитата Сообщение от vxg Посмотреть сообщение
функция WSAWaitForMultipleEvents может ждать сколько угодно событий каких угодно типов, но, поскольку она вызвана с бесконечным таймаутом, это, в рассматриваемом случае, эквивалентно останову выполнения программы до момента приема подключения. что ничем не отличается от accept.
Ну если рассматривать функции только с точки зрения блокировки вызывающего кода,
что, на мой взгляд, несколько однобоко, тогда да, они эквивалентны.
0
5 / 4 / 1
Регистрация: 16.08.2013
Сообщений: 110
13.12.2013, 13:19  [ТС]
а есть клиентская часть?

Добавлено через 14 минут
вот переработал Вашу реализацию под приём сообщений , из консоли всё работает, спасибо) переношу на форму так чтобы этот код срабатывал от нажатия кнопки "создать сервер", и почем то зависает, или страшнее того блокируется) подскажите может есть какие-то различия?
C++
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
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
 
WSADATA wsa_data;
SOCKET s;
SOCKADDR_IN sa;
int select_res = 0;
SOCKET ns;
SOCKADDR_IN nsa;
int sizeof_nsa;
char str[255] = "";
 
int main(int argc, char* argv[])
{
    WSAStartup(0x101, &wsa_data);
    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    sa.sin_family = AF_INET;
    sa.sin_port = htons(5000);
    sa.sin_addr.S_un.S_addr = INADDR_ANY;
    bind(s, (SOCKADDR *)&sa, sizeof(sa));
    listen(s, SOMAXCONN);
    while (true)
    {
        fd_set s_set;
        FD_ZERO(&s_set);
        FD_SET(s, &s_set);
        timeval timeout = {0, 0};
        select_res = select(s + 1, &s_set, 0, 0, &timeout);
        if (select_res) break;
 
        Sleep(250);
    }
    sizeof_nsa = sizeof(nsa);
    ns = accept(s, (SOCKADDR *)&nsa, &sizeof_nsa);
    while(1){
        recv(ns, (char*)&str, sizeof(str), 0);
        printf(str);
    }
    closesocket(ns);
    closesocket(s);
    WSACleanup();
    return 0;
}
Добавлено через 10 минут
заметил в Вашем коде переменную nsa но не нашёл где ей присваивается значение
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,454
13.12.2013, 19:30
Цитата Сообщение от PanKiller Посмотреть сообщение
зависает
на форме вам придется работать по другому:
1 по нажатию кнопки "создать сервер" создать сокет, связать с адресом, поставить на прослушивание
2 в таймере проверять наличие входящих подключений (вызывать select) и если подключение есть - принимать его - таймер будет у вас эквивалентом цикла
3 после приема подключения делать то на что рассчитана ваша программа. как вариант - в другом таймере проверять наличие входящих данных и если они есть - принимать, обрабатывать их и, возможно, отвечать
как альтернатива - можно цикл реализовать не таймером, а поместить в поток, но у потоков свои особенности - просто так обращаться к форме или данным оттуда скорее всего не получится.
Цитата Сообщение от PanKiller Посмотреть сообщение
где ей присваивается значение
его присваивает accept

Добавлено через 7 минут
Цитата Сообщение от Убежденный Посмотреть сообщение
Ну если рассматривать функции только с точки зрения блокировки вызывающего кода,
что, на мой взгляд, несколько однобоко, тогда да, они эквивалентны.
если честно, я (видимо в силу своей зашоренности) не вижу отличий данной функции от select. и та и та проверяет не произошло ли для сокета определенного события. бегло просмотрев WSAWaitForMultipleEvents обнаружил что она ловит все те же события кроме разве что FD_QOS, FD_ROUTING_ INTERFACE_CHANGE, FD_ADDRESS_ LIST_CHANGE, хотя может и select их ловит просто повода не было, а не было его ибо не было нужды в такой экзотике. разница может быть только в реализации. они шибко отличаются в кодах процессора?

Добавлено через 35 секунд
Цитата Сообщение от PanKiller Посмотреть сообщение
а есть клиентская часть?
была такая
C++
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
#include <winsock>
#include <sys/stat.h>
#include <stdio.h>
 
int main(int argc, char* argv[])
{
    char *server_ip = "127.0.0.1";
    int server_port = 5500;
    char *file_name = "test.txt";
    int part_size = 1024;
 
    WSADATA wsa_data;
    if (WSAStartup(0x101, &wsa_data))
    {
        printf("WSAStartup error\n");
        system("pause");
        return -1;
    }
    if (wsa_data.wVersion != 0x101)
    {
        printf("WSA version error\n");
        system("pause");
        return -1;
    }
 
    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s == INVALID_SOCKET)
    {
        printf("socket error\n");
        system("pause");
        return -1;
    }
 
    SOCKADDR_IN sa;
    sa.sin_family = AF_INET;
    sa.sin_port = htons(server_port);
    sa.sin_addr.S_un.S_addr = inet_addr(server_ip);
 
    printf("wait for server...");
    while (true)
    {
        int connect_res = connect(s, (SOCKADDR *)&sa, sizeof(sa));
        if (!connect_res) break;
 
        Sleep(250);
    }
    printf("connected\n");
 
    printf("transfer...");
 
    struct stat si;
    if (stat(file_name, &si))
    {
        printf("stat error\n");
        system("pause");
        return -1;
    }
 
    if (send(s, (char *)&si.st_size, sizeof(si.st_size), 0) == SOCKET_ERROR)
    {
        printf("send error\n");
        system("pause");
        return -1;
    }
 
    int parts_count = si.st_size / part_size;
    int last_part_size = si.st_size % part_size;
 
    FILE *f = fopen(file_name, "rb");
    if (!f)
    {
        printf("fopen error\n");
        system("pause");
        return -1;
    }
 
    char *buffer = new char[part_size];
 
    for (int i = 0; i < parts_count; i++)
    {
        if (fread(buffer, 1, part_size, f) != part_size)
        {
            printf("fread error\n");
            system("pause");
            return -1;
        }
        if (send(s, buffer, part_size, 0) == SOCKET_ERROR)
        {
            printf("send error\n");
            system("pause");
            return -1;
        }
    }
 
    if (last_part_size)
    {
        if (fread(buffer, 1, last_part_size, f) != last_part_size)
        {
            printf("fread error\n");
            system("pause");
            return -1;
        }
        if (send(s, buffer, last_part_size, 0) == SOCKET_ERROR)
        {
            printf("send error\n");
            system("pause");
            return -1;
        }
    }
 
    delete [] buffer;
 
    fclose(f);
 
    closesocket(s);
 
    printf("complete\n");
 
    WSACleanup();
 
    system("pause");
    return 0;
}
1
5 / 4 / 1
Регистрация: 16.08.2013
Сообщений: 110
13.12.2013, 20:07  [ТС]
Цитата Сообщение от vxg Посмотреть сообщение
на форме вам придется работать по другому:
1 по нажатию кнопки "создать сервер" создать сокет, связать с адресом, поставить на прослушивание
2 в таймере проверять наличие входящих подключений (вызывать select) и если подключение есть - принимать его - таймер будет у вас эквивалентом цикла
3 после приема подключения делать то на что рассчитана ваша программа. как вариант - в другом таймере проверять наличие входящих данных и если они есть - принимать, обрабатывать их и, возможно, отвечать
как альтернатива - можно цикл реализовать не таймером, а поместить в поток, но у потоков свои особенности - просто так обращаться к форме или данным оттуда скорее всего не получится.
эти три пункта должны быть реализованы в одной функции (обработчике кнопки?)
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,454
13.12.2013, 20:18
Цитата Сообщение от PanKiller Посмотреть сообщение
эти три пункта должны быть реализованы в одной функции (обработчике кнопки?)
нет. в кнопке только создается сервер. если вы хотите создавать сервер именно по нажатию кнопки. как вариант его можно создавать при запуске программы.
таймеры - это такие штуковины, они наверняка должны быть в вашей визуальной среде о которой мы до сих пор ничего не знаем
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
13.12.2013, 22:13
Цитата Сообщение от vxg Посмотреть сообщение
не вижу отличий данной функции от select. и та и та проверяет не произошло ли для сокета определенного события. бегло просмотрев WSAWaitForMultipleEvents обнаружил что она ловит все те же события кроме разве что FD_QOS, FD_ROUTING_ INTERFACE_CHANGE, FD_ADDRESS_ LIST_CHANGE, хотя может и select их ловит просто повода не было, а не было его ибо не было нужды в такой экзотике. разница может быть только в реализации. они шибко отличаются в кодах процессора?
Теперь понял, о чем Вы говорите. В том смысле, что не об accept речь.
Да, select и WSAEventSelect/WSAWaitForMultipleEvents ничем принципиальным друг от друга не отличаются.
Можно сказать, что первое - это стандарт, а второе - его адаптация для Windows с учетом ее
специфики (асинхронный I/O, наличие в сетевом стеке всяких провайдеров и тому подобное).

В Windows все равно весь ввод-вывод в итоге сводится к стандартному обобщенному интерфейсу, который
крутится вокруг абстракции под названием "файл" (за которой может скрываться все, что угодно):
"создание I/O-запроса - ожидание - перевод дескриптора в сигнальное состояние - завершение запроса",
все в асинхронном ключе, разумеется. Сокеты в этом плане не исключение, а различные модели работы с
ними (блокирующий и неблокирующий режимы, select/WSAEventSelect, socket extensions и т.д.) являются
просто обертками над этим интерфейсом, и если спуститься по сетевому стеку Windows ниже winsock,
никаких select-ов мы там уже не увидим. Вопрос лишь в толщине (или тонкости) этих оберток и в том,
насколько сильно они "искажают суть" реального I/O, который скрывается у них под капотом, где-то
там, в глубине...

...видимо в силу своей зашоренности...
Уверен, что это не более, чем скромность

Оффтоп:
Кстати, а как в других (не-Windows) системах решается проблема select ? На Windows что select, что
wait-функции могут обслужить за один вызов строго ограниченное количество дескрипторов, из-за этого
модель select не особо популярна, но есть порт завершения, например, который свободен от многих
проблем и позволяет делать эффективно и масштабируемо...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
13.12.2013, 22:13
Помогаю со студенческими работами здесь

accept
Можно ли как то устанавливать тайм-аут для этой функции ?

Подвисает accept
Всем привет! У меня сокетный сервер написан на С++, а клиент на Java. Все прекрасно работает на Windows 8. Поставил систему на Windows...

accept не соединяет
#include &quot;stdafx.h&quot; #include &lt;winsock2.h&gt; #include &lt;windows.h&gt; const int WM_SERVER_ACCEPT = WM_USER+1; HWND hwnd; ...

Функция accept
Здравствуйте уважаемые программисты! Помогите разобраться с основами. Вот я на основе этой статьи написал программу, которая связывает два...

accept error
Ругается на accept... собственно почему? (п.с. под windows всё ок...) int sClient; sockaddr_in client_addr; int client_addr_size...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru