Socket non blocking windows

ioctlsocket function (winsock.h)

The ioctlsocket function controls the I/O mode of a socket.

Syntax

Parameters

A descriptor identifying a socket.

A command to perform on the socket s.

A pointer to a parameter for cmd.

Return value

Upon successful completion, the ioctlsocket returns zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.

Error code Meaning
WSANOTINITIALISED A successful WSAStartup call must occur before using this function.
WSAENETDOWN The network subsystem has failed.
WSAEINPROGRESS A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.
WSAENOTSOCK The descriptor s is not a socket.
WSAEFAULT The argp parameter is not a valid part of the user address space.

Remarks

The ioctlsocket function can be used on any socket in any state. It is used to set or retrieve some operating parameters associated with the socket, independent of the protocol and communications subsystem. Here are the supported commands to use in the cmd parameter and their semantics:

The WSAIoctl function is used to set or retrieve operating parameters associated with the socket, the transport protocol, or the communications subsystem.

The WSAIoctl function is more powerful than the ioctlsocket function and supports a large number of possible values for the operating parameters to set or retrieve.

Example Code

Compatibility

WindowsВ PhoneВ 8: This function is supported for Windows Phone Store apps on WindowsВ PhoneВ 8 and later.

WindowsВ 8.1 and Windows ServerВ 2012В R2: This function is supported for Windows Store apps on WindowsВ 8.1, Windows ServerВ 2012В R2, and later.

Сокеты Windows. Блокировка Windows Sockets: Blocking

В этой статье и двух сопутствующих статьях объясняются некоторые проблемы, связанные с программированием Windows Sockets. This article and two companion articles explain several issues in Windows Sockets programming. В этой статье рассматривается блокировка. This article covers blocking. Другие проблемы описаны в статьях: сокеты Windows: порядок байтов и сокеты Windows: преобразование строк. The other issues are covered in the articles: Windows Sockets: Byte Ordering and Windows Sockets: Converting Strings.

Если вы используете или наследуете от класса CAsyncSocket, вам придется самостоятельно управлять этими проблемами. If you use or derive from class CAsyncSocket, you will need to manage these issues yourself. Если вы используете или наследуете от класса CSocket, MFC управляет ими. If you use or derive from class CSocket, MFC manages them for you.

Блокировка Blocking

Сокет может находиться в режиме блокирования или в неблокирующем режиме. A socket can be in «blocking mode» or «nonblocking mode.» Функции сокетов в блокирующем (или синхронном) режиме не возвращают, пока они не смогут завершить действие. The functions of sockets in blocking (or synchronous) mode do not return until they can complete their action. Это называется блокировкой, так как сокет, функция которого была вызвана, не может ничего делать — блокируется, пока вызов не вернет. This is called blocking because the socket whose function was called cannot do anything — is blocked — until the call returns. Например, вызов Receive функции-члена может занять произвольное время, так как ожидает отправки отправляющего приложения (это происходит, если используется CSocket или используется CAsyncSocket with Block). A call to the Receive member function, for example, might take an arbitrarily long time to complete as it waits for the sending application to send (this is if you are using CSocket , or using CAsyncSocket with blocking). Если CAsyncSocket объект находится в неблокирующем режиме (работает асинхронно), вызов возвращается немедленно, а текущий код ошибки, который может быть получен с помощью функции-члена GetLastError , является всаеваулдблокк, указывающим, что вызов был заблокирован, так как он не был возвращен немедленно из-за режима. If a CAsyncSocket object is in nonblocking mode (operating asynchronously), the call returns immediately and the current error code, retrievable with the GetLastError member function, is WSAEWOULDBLOCK, indicating that the call would have blocked had it not returned immediately because of the mode. ( CSocket никогда не возвращает всаеваулдблокк. ( CSocket never returns WSAEWOULDBLOCK. Класс управляет блокировкой.) The class manages blocking for you.)

Читайте также:  Pascal turbo для windows x64

Поведение сокетов отличается от 32-разрядных и 64-разрядных операционных систем (например, Windows 95 или Windows 98), чем в 16-разрядных операционных системах (например, Windows 3,1). The behavior of sockets is different under 32-bit and 64-bit operating systems (such as Windows 95 or Windows 98) than under 16-bit operating systems (such as Windows 3.1). В отличие от 16-разрядных операционных систем, 32-разрядные и 64-разрядные операционные системы используют вытесненное многозадачность и обеспечивают многопоточность. Unlike 16-bit operating systems, the 32-bit and 64-bit operating systems use preemptive multitasking and provide multithreading. В 32-разрядных и 64-разрядных операционных системах можно разместить сокеты в отдельных рабочих потоках. Under the 32-bit and 64-bit operating systems, you can put your sockets in separate worker threads. Сокет в потоке может блокироваться, не мешая другим действиям в приложении и не тратя время на блокировку. A socket in a thread can block without interfering with other activities in your application and without spending compute time on the blocking. Сведения о многопоточном программировании см. в статье многопоточность. For information on multithreaded programming, see the article Multithreading.

В многопоточных приложениях можно использовать блокирующую природу, CSocket чтобы упростить структуру программы, не влияя на скорость реагирования пользовательского интерфейса. In multithreaded applications, you can use the blocking nature of CSocket to simplify your program’s design without affecting the responsiveness of the user interface. При обработке взаимодействия пользователя в основном потоке и CSocket обработке в других потоках эти логические операции можно разделить. By handling user interactions in the main thread and CSocket processing in alternate threads, you can separate these logical operations. В приложении, которое не является многопоточным, эти два действия должны быть объединены и обработаны как единый поток, что обычно означает использование, CAsyncSocket поэтому вы можете обрабатывать запросы на обмен сообщениями по требованию или переопределять CSocket::OnMessagePending их для обработки действий пользователя во время длительной синхронной активности. In an application that is not multithreaded, these two activities must be combined and handled as a single thread, which usually means using CAsyncSocket so you can handle communications requests on demand, or overriding CSocket::OnMessagePending to handle user actions during lengthy synchronous activity.

Оставшаяся часть этого обсуждения предназначена для программистов, предназначенных для 16-разрядных операционных систем: The rest of this discussion is for programmers targeting 16-bit operating systems:

Обычно, если используется CAsyncSocket , не следует использовать блокирующие операции и выполнять асинхронную работу. Normally, if you are using CAsyncSocket , you should avoid using blocking operations and operate asynchronously instead. В асинхронных операциях с момента, когда вы получаете код ошибки всаеваулдблокк после вызова Receive , например, вы ждете, пока не будет OnReceive вызвана функция-член, чтобы уведомить о возможности повторного чтения. In asynchronous operations, from the point at which you receive a WSAEWOULDBLOCK error code after calling Receive , for example, you wait until your OnReceive member function is called to notify you that you can read again. Асинхронные вызовы выполняются путем вызова обратной функции уведомления о обратном вызове сокета, например OnReceive. Asynchronous calls are made by calling back your socket’s appropriate callback notification function, such as OnReceive.

Читайте также:  Зимние скринсейверы для windows 10

В Windows блокирующие вызовы считаются неправильными. Under Windows, blocking calls are considered bad practice. По умолчанию CAsyncSocket поддерживает асинхронные вызовы, и вам необходимо самостоятельно управлять блокировкой с помощью уведомлений обратного вызова. By default, CAsyncSocket supports asynchronous calls, and you must manage the blocking yourself using callback notifications. Класс CSocket, с другой стороны, является синхронным. Class CSocket, on the other hand, is synchronous. Она переносит сообщения Windows и управляет блокировками. It pumps Windows messages and manages blocking for you.

Дополнительные сведения о блокировке см. в описании спецификации сокетов Windows. For more information about blocking, see the Windows Sockets specification. Дополнительные сведения о функциях «on» см. в разделе сокеты Windows: уведомления сокетов и сокеты Windows: производные от классов сокетов. For more information about «On» functions, see Windows Sockets: Socket Notifications and Windows Sockets: Deriving from Socket Classes.

Дополнительные сведения см. в разделе: For more information, see:

Определение blocking-режима TCP-сокета под Windows

Те, кто работает с TCP-сокетами, знают что сокет может работать в блокирующем или неблокирующем (nonblocking) режиме. Windows-сокеты, после создания, находятся в блокирующем режиме, но их можно перевести в неблокирующий функцией ioctlsocket().

При работе над одним проектом у меня появилась задача определить, в каком режиме работает сокет, предоставленный мне DLL-функцией. Т.е. кроме самого сокета, у меня никакой информации не было и приходили они в непредсказуемом режиме.

Под *nix blocking-режим без проблем определяется вызовом функции fcntl(), но под WinSock2 ничего подобного не обнаружилось, и на форумах ничего кроме «Windows does not offer any way to query whether a socket is currently set to blocking or non-blocking» никто не ответил.

Но способ определения все-таки существует:

Функция принимает номер сокета и возвращает 1 если сокет в nonblocking mode, 0 — blocking, -1 если произошла ошибка определения и -2 если сокет после определения режима остался с маленьким таймаутом.

Вкратце последовательность действий такова:

1. Сохраняем значение таймаута сокета (по умолчанию там 0 — «ждать вечно»).
2. Устанавливаем таймаут в 1 милисекунду.
3. Читаем из сокета 0 (ноль) байт Out of Band данных. Тут нужно пояснение: Если передаются OOB-данные, то функция может врать, но я никогда не сталкивался с OOB с тех пор, как Windows NT4 валилась в синий экран при попытке принять такое (WinNuke).
4. Получаем ошибку, которая произошла в результате чтения.
5. Восстанавливаем старое значение таймаута сокета.
6. Смотрим что за ошибка чтения у нам была: если WSAEWOULDBLOCK — то сокет находится в nonblocking mode, что и требовалось определить.

К недостаткам данного метода, кроме уже упомянутого MSG_OOB, можно отнести задержку определения в 1 миллисекунду и ненулевую вероятность испортить таймаут чтения сокета (хотя нагрузочный тест ни разу такого поведения не выявил).

How to make ‘send’ non-blocking in winsock

I am making a program which sends UDP packets to a server at a fixed interval, something like this:

However the periodicity cannot be guaranteed because send is a blocking call (e.g., when fixedInterval is 20ms, and a call to send is > 20ms ). Do you know how I can turn the send into a non-blocking operation?

4 Answers 4

The API ioctlsocket can do it.You can use it as below.But why don’t you use I/O models in winsock?

You need to use a non-blocking socket. The send/receive functions are the same functions for blocking or non-blocking operations, but you must set the socket itself to non-blocking.

Also, be aware that working with non-blocking sockets is quite different. You’ll need to make sure you handle WSAEWOULDBLOCK errors as success! 🙂

Читайте также:  Как узнать свои порты linux

So, using non-blocking sockets may help, but still will not guarantee an exact period. You would be better to drive this from a timer, rather than this simple loop, so that any latency from calling send, even in non-blocking mode, will not affect the timing.

My memory is fuzzy here since it’s probably been 15 years since I’ve used UDP non-blocking.

However, there are some things of which you should be aware.

Send only smallish packets if you’re going over a public network. The PATH MTU can trip you up if either the client or the server is not written to take care of incomplete packets.

Make sure you check that you have sent the number of bytes you think you have to send. It can get weird when you’re expecting to see 300 bytes sent and the receiving end only gets 248. Both client side and server side have to be aware of this issue.

See here for some good advice from the Linux folks.

See here for the Unix Socket FAQ for UDP

This is a good, general network programming FAQ and example page.

non-blocking udp socket programming in C: what do I get?

I have a problem in understanding what recv()/recvfrom() return from an non-blockig UDP socket.

A bit more specific and compared to TCP (please correct me if I’m wrong):

A blocking socket (either TCP or UDP) won’t return from a recv() until there is some data in the buffer. This could be some number of bytes (TCP) or a complete datagram (UDP).

A non-blocking TCP socket either returns EWOULDBLOCK (linux) / WSAEWOULDBLOCK (windows) or the bytes that are currently in the buffer. As TCP data is a stream it doesn’t matter how many bytes are returned.

Now the question:

  • A non-blocking UDP socket also returns WOULDBLOCK (linux) / WSAEWOULDBLOCK (windows) if there is no data available. But if there is data availabe, does a non-blocking UDP socket return just some bytes, which could mean you only get half of a datagram OR does an UDP socket always return complete datagrams??

What I mean with «half of a datagram» is: what happens if I call recv() in just the moment when the socket is currently receiving a datagram. In that moment there are some bytes in the buffer but the datagram isn’t complete yet.

Your explanations and comments are appreciated. Thanks!

3 Answers 3

Finally, an excuse to dig out my Stevens books from my old office boxes.

Provided the buffer is large enough, the standard Berkeley sockets recv() and recvfrom() functions will never return a partial datagram. The datagram is not available to the application until the kernel has completely received and reassembled the datagram.

Interestingly, and this isn’t much (any?) of an issue today, other network programming interfaces don’t agree on the behavior when the provided buffer is too small:

The traditional Berkeley version of the sockets API truncates the datagram, discarding any excess data. Whether the application is notified depends on the version. (4.3BSD Reno and later can notify the application that the datagram was truncated.)

The sockets API under SVR4 (including Solaris 2.x) does not truncate the datagram. Any excess data is returned in subsequent reads. The application is not notified that multiple reads are being fulfilled from a single UDP datagram.

The TLI API does not discard the data. Instead a flag is returned indicating that more data is available, and subsequent reads by the application return the rest of the datagram.

(Stevens, TCP/IP Illustrated, Volume 1, p. 160)

Оцените статью