Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
32 / 30 / 4
Регистрация: 01.02.2014
Сообщений: 878

Как правильно работать в wisocket?

14.10.2017, 10:41. Показов 2305. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Конкретно пару вопросов,
в мунале есть слова о том что для каждого успешного вызова WSAStartup нужно вызвать WSACleanup, я обычно вызываю WSAStartup в конструкторе программы, а WSACleanup в деструкторе, но раз есть возможность вызывать их несколько раз значит наверно есть в этом смысл?
Например я использую сокеты в потоках, может мне в каждом потоке надо их вызывать а не для всего приложения сразу? вдруг например он там в стек ошибки записывает и таким образом память растет..

Добавлено через 3 минуты
и еще вопрос

есть код
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
struct sockaddr_in addr;
addr.sin_addr.s_addr = inet_addr( host.toLocal8Bit().data() );
    if( INADDR_NONE == addr.sin_addr.s_addr )
    {
        struct hostent *h = gethostbyname( host.toLatin1().data() );
        if( !h )
        {
            err = WSAGetLastError( );
            Error = "Не найден домен";
            return 0;
        }
        addr.sin_addr = *(struct in_addr *) h->h_addr_list[0];
    }
    addr.sin_family = AF_INET;
    addr.sin_port       = htons( _port );
 
    // Соединение с сервером
    if( ::connect( this->socket, ( const struct sockaddr* )&addr, sizeof(addr) ) == SOCKET_ERROR )
    {
        err = WSAGetLastError( );
        Error = "Ошибка при подключении к сайту";
        return 0;
    }
в данном случае мне же надо вызывать freeaddrinfo для очистки sockaddr_in или нет? а как быть с структурой hostent ?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
14.10.2017, 10:41
Ответы с готовыми решениями:

Как правильно работать с БД
Visual Studio 2015 VB.NET 4.5.2 + SQL Подскажите плиз след. вопрос: Есть у меня допустим прога(оболочка) для БД. Хочу иметь возможность...

Как правильно работать с Recordset
Здравствуйте. Сейчас данные получаю так: SQLText = "select t.znach from chasspt t where t.kodobject=50 and t.kodparam =24 and...

Как правильно работать с JSON?
Здравствуйте! Подскажите, как правильно обрабатывать JSON в PHP, чтобы избежать монструозных конструкций такого вида: $userName=...

20
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
14.10.2017, 10:52
Цитата Сообщение от mh-coder Посмотреть сообщение
в мунале есть слова о том что для каждого успешного вызова WSAStartup нужно вызвать WSACleanup, я обычно вызываю WSAStartup в конструкторе программы, а WSACleanup в деструкторе, но раз есть возможность вызывать их несколько раз значит наверно есть в этом смысл?
Смысл в том, что приложения могут быть очень большими и состоять из множества компонентов,
которые "не знают" друг про друга ничего. В таких системах WSAStartup/WSACleanup могут
вызываться много-много раз, даже из одного потока...

Цитата Сообщение от mh-coder Посмотреть сообщение
в данном случае мне же надо вызывать freeaddrinfo для очистки или нет?
Не увидел, где здесь может потребоваться вызов freeaddrinfo.
1
32 / 30 / 4
Регистрация: 01.02.2014
Сообщений: 878
14.10.2017, 11:27  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Не увидел, где здесь может потребоваться вызов freeaddrinfo.
ну например
C++ (Qt)
1
struct hostent *h = gethostbyname( host.toLatin1().data() );
gethostbyname не пойму как работает, она не вызывает для имени домена malloc для того чтобы вернуть новую строку с именем домена? которая хранится потом в addr.sin_addr ?

правильно ли вообще так делать?
C++ (Qt)
1
addr.sin_addr = *(struct in_addr *) h->h_addr_list[0];

ну и по поводу ошибок, они где-то хранятся в стеке? или сохраняется только последняя которую вызывает WSAGetLastError( ) ?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
15.10.2017, 08:19
Цитата Сообщение от mh-coder Посмотреть сообщение
gethostbyname не пойму как работает, она не вызывает для имени домена malloc для того чтобы вернуть новую строку с именем домена? которая хранится потом в addr.sin_addr ?
Да, gethostbyname выделяет память под hostent, но освобождать ее самому не нужно,
это делает WinSock в нужный момент - когда ты в следующий раз вызываешь gethostbyname и,
очевидно, когда вызывается самый последний WSACleanup.
Ну то есть, использовать здесь freeaddrinfo/free/etc здесь было бы грубой ошибкой.

Как пишет MSDN, указатель на выделенную память хранится в блоке памяти потока
(TLS - Thread Local Storage).

Цитата Сообщение от mh-coder Посмотреть сообщение
правильно ли вообще так делать?
Правильно. Только надо сначала проверить, что в h->h_addr_list[i] лежит не NULL,
иначе произойдет разыменование нулевого указателя.

Цитата Сообщение от mh-coder Посмотреть сообщение
ну и по поводу ошибок, они где-то хранятся в стеке? или сохраняется только последняя которую вызывает WSAGetLastError( ) ?
Когда происходит какая-то ошибка, система записывает ее код в память потока.
Если быть точным, коды GetLastError и WSAGetLastError, - а это одно и то же, -
хранятся в TEB (Thread Information Block) - специальной структуре, которая есть у
каждого потока Win32.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
13.11.2019, 19:41
Цитата Сообщение от Убежденный Посмотреть сообщение
... В таких системах WSAStartup/WSACleanup могут
вызываться много-много раз, даже из одного потока...
Здравствуйте,
Подскажите пожалуйста, а зачем много раз вызывать WSAStartup и WSACleanup, ведь WSACleanup - это просто ициниализация самого Winsock. ?

И если не сложно подскажите пожалуйста:

C++
1
SOCKET WSAAPI socket(int af, int type, int protocol);
Что такое WSAAPI ? Все что нагуглил, это некий define, который заменяет WSAAPI на __stdcall, но что такое в итоге __stdcall, зачем он нужен и зачем он вызывается и зачем писать WSAAPI, а не сразу __stdcall - не понял, совершенно.

Это некое соглашение о вызовах, но что будет катострафического, если запустить без него ? По факту работает, но, что потенциально может случится ?
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
13.11.2019, 20:27
Цитата Сообщение от Optimus11 Посмотреть сообщение
но что такое в итоге __stdcall, зачем он нужен
Это соглашение о вызове. Этим соглашением определяется способ передачи параметров, кто чистит стек и т.д.
Цитата Сообщение от Optimus11 Посмотреть сообщение
и зачем писать WSAAPI, а не сразу __stdcall - не понял, совершенно.
Потому что __stdcall - не является частью C или C++.
Это стороннее ключевое слово.
На одном компиляторе соглашение вызова пишется как __stdcall, на другом, например, как __attribute__((stdcall)).
Используя макрос, мы даем разработчикам возможность прописывать соглашение вызова универсально.
#define WSAAPI stdcall - на одном
#define WSAAPI __stdcall - на другом
#define WSAAPI __attribute__((stdcall)) - на третьем
Если используется WSAAPI, то пользовательский код не меняется от компилятора к компилятору.
Цитата Сообщение от Optimus11 Посмотреть сообщение
но что будет катострафического, если запустить без него ?
Скорее всего, всё рухнет. По-умолчанию C и C++ используют соглашение cdecl.
WinAPI использует stdcall.
Например, оконная процедура может быть и cdecl и stdcall.
Так-то она должна быть stdcall, но для дураков сделали защиту.
Цитата Сообщение от Optimus11 Посмотреть сообщение
По факту работает,
Как проверял?
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
13.11.2019, 20:44
Цитата Сообщение от Croessmah Посмотреть сообщение
Как проверял?
Ну пока что просто создал сокет. Никаких send recv пока не делал.
Но код скомилировался, припроверке аозвращенного значения socket != invalid_socket все нормально.
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
13.11.2019, 20:51
Optimus11, socket объявлена в потрохах компилятора.
В объявлении указано, что она использует __stdcall.
При вызове компилятор строит код под это соглашение.

Если просто поменять объявление, то получим undefined reference,
т.к. соглашение влияет на декорирование имен.

Добавлено через 3 минуты
https://en.wikibooks.org/wiki/... onventions
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
13.11.2019, 21:15
C++
1
2
3
STDCALL
 
The called function cleans the stack, unlike CDECL.
Тут вроде понятно, вызванная функция, сама очищает стек.

А вот тут не очень:
C++
1
2
3
4
CDECL
In the CDECL calling convention the following holds:
 
The calling function cleans the stack.
Вызывающая функция очищает стек. Что значит вызывающая функция, что в данном случае за функция, которая вызывает ? Имеется ввиду, что нужно самому подчистить при завершении вызванной функции ?
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
13.11.2019, 21:33
Цитата Сообщение от Optimus11 Посмотреть сообщение
Что значит вызывающая функция
Та, которая вызывает.
C++
1
2
3
4
void bar() //<-- вызывающая
{
   foo(); //<-- вызываемая
}
Цитата Сообщение от Optimus11 Посмотреть сообщение
Имеется ввиду, что нужно самому подчистить при завершении вызванной функции ?
Да. Вызвали функцию - почистили за ней.
Если пишите на ассемблере, то руками.
На C и C++ код очистки построит компилятор.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
17.11.2019, 16:14
Здравствувйте,

Подскажите пожалуйста:

Вот когда создаем сокет:

C++
1
SOCKET WSAAPI socket(af, type, protocol);
B параметре af - указываем семейство протоколов, в данном случае это интернет протоколы ipv4(AF_INET) и ipv6(AF_INET6).

И вот вопрос: делая запрос к какому либо сайту, я ведь не знаю, какой он из протоколов сейчас поддерживает старый или новый, и если поставить ipv4(AF_INET), то к серверу работающему на ipv6 - подключение не произойдет ведь ?

То есть просто нужно сразу выбирать ipv6(AF_INET6) и просто указывать адрес ipv4 с 128 битном формате ipv6 ?
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
19.11.2019, 19:35
Здравствуйте,

Просто интересно:

при создании сокета, уже указывается семейство протоколов (параметр af):
C++
1
2
3
4
5
6
7
SOCKET WSAAPI my_socket;
 
int af = AF_INET;
int type = SOCK_STREAM;
int protocol = IPPROTO_TCP;
 
my_socket = socket(af, type, protocol); // где af -  соответствует ipv4
Но при вызове коннекта к соотвествующему адресу:
C++
1
int WSAAPI connect(SOCKET my_socket, const struct sockaddr FAR *name, int namelen);
//где struct sockaddr:

C++
1
2
3
4
5
6
struct sockaddr_in{
                      short sin_family; // опять зачем то необходимо заподнять семейство протоколов, хотя этот параметр уже был указан при создании сокета в параметре - af
                      u_short sin_port; 
                      struct in_addr sin_addr;
                      char sin_zero[8];
                      };
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
20.11.2019, 18:42
И вот вопрос: делая запрос к какому либо сайту, я ведь не знаю, какой он из протоколов сейчас поддерживает старый или новый, и если поставить ipv4(AF_INET), то к серверу работающему на ipv6 - подключение не произойдет ведь ?
Ну подскажите пожалуйста по данному вопросу? Что то не могу ни как сообразить
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
20.11.2019, 19:12
Optimus11, может Вы уже свою тему создадите?

Цитата Сообщение от Optimus11 Посмотреть сообщение
хотя этот параметр уже был указан при создании сокета в параметре - af
По идее, в socket нужно пихать PF_INET, а не AF_INET, т.к. они несколько разные вещи обозначают. Но эти константы всегда были равны, и PF_INET уже не используется. Но это не точно.
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
20.11.2019, 19:22
Цитата Сообщение от Croessmah Посмотреть сообщение
Optimus11, может Вы уже свою тему создадите?


По идее, в socket нужно пихать PF_INET, а не AF_INET, т.к. они несколько разные вещи обозначают. Но эти константы всегда были равны, и PF_INET уже не используется. Но это не точно.
С msdn:
C++
1
Обратите внимание, что значения констант семейства адресов AF_ и семейства протоколов PF_ идентичны (например, AF_INET и PF_INET ), поэтому можно использовать любую константу.
Но на вопрос то это не отвечает, af_inet относится к ipv4, af_inet6 к ipv6, но как я создам сокет, заранее , если я не знаю на каком протоколе рабоьает запрашиваемый сайт ?
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
20.11.2019, 20:08
Цитата Сообщение от Optimus11 Посмотреть сообщение
С msdn:
Особенно приятно, что socket функция идет от юниксов.
http://man7.org/linux/man-pages/man2/socket.2.html
The manifest constants used under 4.x BSD for protocol families are PF_UNIX, PF_INET, and so on, while AF_UNIX, AF_INET, and so on are used for address families. However, already the BSD man page promises: "The protocol family generally is the same as the address family", and subsequent standards use AF_* everywhere.
https://beej.us/guide/bgnet/html/
(This PF_INET thing is a close relative of the AF_INET that you can use when initializing the sin_family field in your struct sockaddr_in. In fact, they’re so closely related that they actually have the same value, and many programmers will call socket() and pass AF_INET as the first argument instead of PF_INET. Now, get some milk and cookies, because it’s time for a story. Once upon a time, a long time ago, it was thought that maybe an address family (what the “AF” in “AF_INET” stands for) might support several protocols that were referred to by their protocol family (what the “PF” in “PF_INET” stands for). That didn’t happen. And they all lived happily ever after, The End. So the most correct thing to do is to use AF_INET in your struct sockaddr_in and PF_INET in your call to socket().)
По последней ссылке можете ответы и на другие вопросы поискать.
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
20.11.2019, 20:33
Все равно не понимаю ((

Смысл использовать pf_inet при создании сокета, af_inet при коннекте ? Какой в этом сакральный смысл, если при конекте я все равно не знаю на какой семействе протоколов обслуживается запрашиваемый сайт.
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
20.11.2019, 20:51
Optimus11, я же сказал искать по ссылке выше.
Процитирую:
I keep saying that servinfo is a linked list with all kinds of address information. Let’s write a quick demo program to show off this information. This short program21 will print the IP addresses for whatever host you specify on the command line
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
/*
** showip.c -- show IP addresses for a host given on the command line
*/
 
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
 
int main(int argc, char *argv[])
{
    struct addrinfo hints, *res, *p;
    int status;
    char ipstr[INET6_ADDRSTRLEN];
 
    if (argc != 2) {
        fprintf(stderr,"usage: showip hostname\n");
        return 1;
    }
 
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
    hints.ai_socktype = SOCK_STREAM;
 
    if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
        return 2;
    }
 
    printf("IP addresses for %s:\n\n", argv[1]);
 
    for(p = res;p != NULL; p = p->ai_next) {
        void *addr;
        char *ipver;
 
        // get the pointer to the address itself,
        // different fields in IPv4 and IPv6:
        if (p->ai_family == AF_INET) { // IPv4
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
            addr = &(ipv4->sin_addr);
            ipver = "IPv4";
        } else { // IPv6
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
            addr = &(ipv6->sin6_addr);
            ipver = "IPv6";
        }
 
        // convert the IP to a string and print it:
        inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
        printf("  %s: %s\n", ipver, ipstr);
    }
 
    freeaddrinfo(res); // free the linked list
 
    return 0;
}
As you see, the code calls getaddrinfo() on whatever you pass on the command line, that fills out the linked list pointed to by res, and then we can iterate over the list and print stuff out or do whatever.

(There’s a little bit of ugliness there where we have to dig into the different types of struct sockaddrs depending on the IP version. Sorry about that! I’m not sure of a better way around it.)

Sample run! Everyone loves screenshots:

Code
1
2
3
4
5
6
7
8
9
10
$ showip www.example.net
IP addresses for www.example.net:
 
  IPv4: 192.0.2.88
 
$ showip ipv6.example.com
IP addresses for ipv6.example.com:
 
  IPv4: 192.0.2.101
  IPv6: 2001:db8:8c00:22::171
Now that we have that under control, we’ll use the results we get from getaddrinfo() to pass to other socket functions and, at long last, get our network connection established! Keep reading!
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
26.11.2019, 14:24
Здравствуйте,

Ни как не могу на сайте microsoft в темах по winsock описание структуры:
C++
1
2
3
4
5
6
7
8
9
10
11
struct in_addr6 {
    u_char    s6_addr[16];             /* IPv6 address */
};
 
struct sockaddr_in6 {
    short             sin6_family;     /* AF_INET6 */
    u_short           sin6_port;       /* Transport level port number */
    u_long            sin6_flowinfo;   /* IPv6 flow information */
    struct in_addr6   sin6_addr;       /* IPv6 address */
    u_long            sin6_scope_id;   /* set of interfaces for a scope */
   };
Или плохо ищу или правда там почему то нет описания.
Ну если с sin6_family и sin6_ port понятно, то что такое sin6_flowinfo и sin6_scope_id и как оно и чем заполняется - непонятно.
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
26.11.2019, 16:01
sin6_flowinfo - The IPv6 flow information.


P.S. Ты так и будешь в чужих старых темах свои вопросы задавать?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
26.11.2019, 16:01
Помогаю со студенческими работами здесь

Как правильно работать с сетками?
Подскажите как распланировать сетку как на мекете до этого накидывал просто готовые варианты. Потом понял что сайт должен быть адаптивный...

Как правильно работать с кириллицей
Если вы пишете программу на QBASIC под Windows XP и вам нужно оперировать с файлами, содержащими русские буквы, соблюдайте ...

Как правильно работать с циклом
при работы с циклом программа зависает. К примеру, цикл из 600 шагов. За это время программа просто напрросто зависает. Могу код кинуть, но...

Как правильно работать с Fragment
Всем привет! Недавно начал изучать программирование под Андройд. На данный момент встал вопрос, который решить не получается. И Так. В...

Как правильно работать с json?
$.ajax({ url: '../feedback.php', /*data: $('#feedbackForm').serialize(),*/ dataType: 'json', type:...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru