функция send (winsock2.h)
Функция отправки отправляет данные в подключенный сокет.
Синтаксис
int WSAAPI send(
[in] SOCKET s,
[in] const char *buf,
[in] int len,
[in] int flags
);
Параметры
[in] s
Дескриптор, определяющий подключенный сокет.
[in] buf
Указатель на буфер, содержащий передаваемые данные.
[in] len
Длина (в байтах) данных в буфере, на которые указывает параметр buf .
[in] flags
Набор флагов, указывающих способ вызова. Этот параметр создается с помощью побитового оператора OR с любым из следующих значений.
Возвращаемое значение
Если ошибка не возникает, функция send возвращает общее количество отправленных байтов, которое может быть меньше числа, запрошенного для отправки в параметре len . В противном случае возвращается значение SOCKET_ERROR, а определенный код ошибки можно получить, вызвав WSAGetLastError.
Код ошибки | Значение |
---|---|
Перед использованием этой функции должен произойти успешный вызов WSAStartup . | |
Произошел сбой сетевой подсистемы. | |
Запрошенный адрес является широковещательным, но соответствующий флаг не установлен. Вызовите setsockopt с параметром сокета SO_BROADCAST, чтобы разрешить использование широковещательного адреса. | |
Блокирующий вызов Windows Sockets 1.1 был отменен через WSACancelBlockingCall. | |
Выполняется блокирующий вызов Windows Sockets 1.1 или поставщик услуг по-прежнему обрабатывает функцию обратного вызова. | |
Параметр buf не полностью содержится в допустимой части адресного пространства пользователя. | |
Подключение было разорвано из-за ошибки во время выполнения операции. | |
Нет свободного места в буфере. | |
Сокет не подключен. | |
Дескриптор не является сокетом. | |
MSG_OOB указано, но сокет не является потоковым, например тип SOCK_STREAM, данные OOB не поддерживаются в домене связи, связанном с этим сокетом, или сокет является однонаправленным и поддерживает только операции получения. | |
Сокет был выключен; невозможно выполнить отправку в сокет после вызова завершения работыс параметром SD_SEND или SD_BOTH. | |
Сокет помечается как неблокировочный, и запрошенная операция будет блокироваться. | |
Сокет ориентирован на сообщения, и сообщение больше максимального значения, поддерживаемого базовым транспортом. | |
В настоящее время с этого узла не удается связаться с удаленным узлом. | |
Сокет не был привязан с помощью привязки, или был указан неизвестный флаг, или MSG_OOB был указан для сокета с включенным SO_OOBINLINE. | |
Виртуальное подключение разорвано из-за тайм-аута или иного сбоя. Приложение должно закрыть сокет, поскольку он больше не может использоваться. | |
Виртуальное подключение было сброшено удаленной стороной путем прерывания. Для сокетов UDP удаленный узел не смог доставить ранее отправленную датаграмму UDP и ответил пакетом ICMP "Порт недоступен". Приложение должно закрыть сокет, поскольку он больше не может использоваться. | |
Подключение было прервано из-за сбоя сети или из-за того, что система на другом конце не работает без предварительного уведомления. |
Комментарии
Функция send используется для записи исходящих данных в подключенный сокет.
Для сокетов, ориентированных на сообщения (например, семейство адресов AF_INET или AF_INET6, тип SOCK_DGRAM и протокол IPPROTO_UDP), следует соблюдать осторожность, чтобы не превышать максимальный размер пакета базового поставщика. Максимальный размер пакета сообщений для поставщика можно получить, вызвав метод getsockopt с параметром optname , равным SO_MAX_MSG_SIZE для получения значения параметра socket. Если данные слишком длинны для атомарной передачи через базовый протокол, возвращается ошибка WSAEMSGSIZE и данные не передаются.
Успешное завершение функции отправки не означает, что данные были успешно доставлены и получены получателю. Эта функция только указывает, что данные были успешно отправлены.
Если в транспортной системе нет буферного пространства для хранения передаваемых данных, отправка будет блокироваться, если сокет не был помещен в неблокировочный режим. В неблокированных сокетах, ориентированных на поток, число записанных байтов может составлять от 1 до требуемой длины в зависимости от доступности буфера как на клиентском, так и на серверном компьютерах. Функции select, WSAsyncSelect или WSAEventSelect можно использовать для определения возможности отправки дополнительных данных.
Вызов отправки с параметром len , равным нулю, допустим и будет рассматриваться реализациями как успешная. В таких случаях send возвращает ноль в качестве допустимого значения. Для сокетов, ориентированных на сообщения, отправляется транспортная датаграмма нулевой длины.
Параметр flags можно использовать для влияния на поведение функции за пределами параметров, указанных для связанного сокета. Семантика функции отправки определяется любыми параметрами, ранее заданными в сокете, указанном в параметре s , и параметром flags, переданным функции отправки .
Порядок вызовов, выполненных для отправки , также является порядком передачи буферов на транспортный уровень. Отправка не должна вызываться в одном потокоориентированном сокете одновременно из разных потоков, так как некоторые поставщики Winsock могут разделить большой запрос на отправку на несколько передач, что может привести к непреднамеренное чередование данных из нескольких одновременных запросов на отправку в одном и том же сокете, ориентированном на поток.
Пример кода
В следующем примере показано использование функции send .#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 27015
int main() {
//----------------------
// Declare and initialize variables.
int iResult;
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
int recvbuflen = DEFAULT_BUFLEN;
char *sendbuf = "Client: sending data test";
char recvbuf[DEFAULT_BUFLEN] = "";
//----------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error: %d\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
clientService.sin_port = htons( DEFAULT_PORT );
//----------------------
// Connect to server.
iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
if (iResult == SOCKET_ERROR) {
wprintf(L"connect failed with error: %d\n", WSAGetLastError() );
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
//----------------------
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
wprintf(L"send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %d\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
wprintf(L"shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 )
wprintf(L"Bytes received: %d\n", iResult);
else if ( iResult == 0 )
wprintf(L"Connection closed\n");
else
wprintf(L"recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
// close the socket
iResult = closesocket(ConnectSocket);
if (iResult == SOCKET_ERROR) {
wprintf(L"close failed with error: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
WSACleanup();
return 0;
}
Пример кода
Другой пример, в котором используется функция отправки, см. в разделе начало работы с Помощью Winsock.Примечания для сокетов IrDA
- Файл заголовка Af_irda.h должен быть явно включен.
Windows 8.1 и Windows Server 2012 R2. Эта функция поддерживается для приложений Магазина Windows на Windows 8.1, Windows Server 2012 R2 и более поздних версиях.
Требования
Требование | Значение |
---|---|
Минимальная версия клиента | Windows 8.1, Windows Vista [классические приложения | Приложения UWP] |
Минимальная версия сервера | Windows Server 2003 [классические приложения | Приложения UWP] |
Целевая платформа | Windows |
Header | winsock2.h |
Библиотека | Ws2_32.lib |
DLL | Ws2_32.dll |