天道酬勤,学无止境

Winsock2 - how to open a TCP socket that allows recv() with MSG_WAITALL?

In this code:

// error checking is omitted

// init Winsock2
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

// connect to server
struct addrinfo *res = NULL, *ptr = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

getaddrinfo(server_ip, "9999", &hints, &res);
SOCKET client_socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

connect(client_socket, res->ai_addr, (int)res->ai_addrlen);

freeaddrinfo(res);
res = NULL;

// read the data
unsinged int size1;
if (recv(client_socket, (char*)&size1, sizeof(int), MSG_WAITALL) == SOCKET_ERROR)
{
    return WSAGetLastError();
}

(note the MSG_WAITALL flag in recv()) everything works fine, expect for recv(). WSAGetLastError() returns WSAEOPNOTSUPP.
MSDN states that

Note that if the underlying transport does not support MSG_WAITALL, or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP. Also, if MSG_WAITALL is specified along with MSG_OOB, MSG_PEEK, or MSG_PARTIAL, then this call will fail with WSAEOPNOTSUPP. This flag is not supported on datagram sockets or message-oriented sockets.

But it doesn't look like I'm doing something from this list. Why my recv() call doesn't work?

标签

评论

it doesn't look like I'm doing something from this list.

Yes, you are - the very first item on the list:

the underlying transport does not support MSG_WAITALL

Microsoft's default TCP transport provider does not support MSG_WAITALL. recv(), and Winsock in general, is not limited to just Microsoft's TCP provider. It supports 3rd party providers, and any transport protocols that the provider supports - TCP, UDP, IPX, ICMP, RAW, etc.

When using Microsoft's TCP, if you want recv() to wait until all of the requested TCP data has been received, you have to set the socket to blocking mode (its default mode) and then set the flags parameter of recv() to 0. But even that is not guaranteed, recv() can return with fewer bytes than requested, so you should be prepared to call recv() in a loop until all intended bytes have actually been received.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 在C ++中使用'recv'和'MSG_PEEK'获取套接字中可用的字节数(Get the number of bytes available in socket by 'recv' with 'MSG_PEEK' in C++)
    问题 C ++具有以下功能,可从套接字接收字节,它可以检查带有MSG_PEEK标志的可用字节数。 使用MSG_PEEK ,返回值'recv'是套接字中可用的字节数: #include <sys/socket.h> ssize_t recv(int socket, void *buffer, size_t length, int flags); 我需要在不创建buffer情况下获得套接字中可用的字节数(不为buffer分配内存)。 有可能吗? 回答1 您要查找的是ioctl(fd,FIONREAD,&bytes_available)和Windows下的ioctlsocket(socket,FIONREAD,&bytes_available) 。 但是请注意,操作系统并不一定保证它将为您缓冲多少数据,因此,如果您正在等待大量数据,则最好先读入数据并将其存储在自己的缓冲区中直到您拥有处理某物所需的一切。 为此,通常要做的是一次只读取块,例如 char buf[4096]; ssize_t bytes_read; do { bytes_read = recv(socket, buf, sizeof(buf), 0); if (bytes_read > 0) { /* do something with buf, such as append it to a larger buffer or
  • Socket recv() hang on large message with MSG_WAITALL
    I have an application that reads large files from a server and hangs frequently on a particular machine. It has worked successfully under RHEL5.2 for a long time. We have recently upgraded to RHEL6.1 and it now hangs regularly. I have created a test app that reproduces the problem. It hangs approx 98 times out of 100. #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/param.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <netdb.h> #include <sys/socket.h> #include <sys/time.h> int mFD = 0; void open_socket() { struct addrinfo
  • Berkeley socket中MSG_WAITALL的机制(Mechanism of MSG_WAITALL in Berkeley socket)
    问题 在 Berkeley 套接字中,是否设置了 MSG_WAITALL 标志的 recv 函数取代了多个读取函数,直到读取了请求的整个数据? 我的意思是 recv 函数是否在一次调用中读取了由大小决定的整个块,而 read 函数可能会读取数据块的一部分,我需要在循环中多次调用它直到读取整个块? 回答1 是的, MSG_WAITALL告诉recv()等待,直到所有请求的字节都被读取。 但是,它仅在阻塞模式下受支持,在非阻塞模式下不受支持,并且它仅适用于面向流的套接字,例如 TCP。 即便如此,您仍然必须循环,例如在 Linux 上,如果recv()被信号中断并且必须再次调用以继续读取。
  • 在 C++ 中刷新套接字(Flush a socket in C++)
    问题 我尝试在 C++ 中调用send函数后刷新套接字。 我使用了winsock2.h库。 我需要在发送消息后立即发送数据,但我找不到任何类似flash功能的功能。 我正在尝试向设备发送消息,它希望一条一条地接收消息。 我的意思是,如果我在发送器中发送两条消息,例如“MessageOne”和“MessageTwo”,接收器会收到不单独的“MessageOneMessageTwo”,并且设备无法识别命令。 那我该怎么做呢? 回答1 您无法在发送方做任何事情来使接收方“一个接一个”地接收消息。 完全是接收方负责正确重建发送的帧(“消息”)。 接收代码必须以某种方式知道消息长度(完全特定于协议)并接收尽可能多的数据以构建整个帧(通常通过发布具有指定长度并指定仅对整个缓冲区感兴趣的 recv 来实现,例如MSG_WAITALL标志)。 我发现很难相信您的设备不知道如何处理这个问题,如果确实如此,您实际上无能为力。 我发现您不了解设备/协议要求并且您问错了问题的可能性更大。 回答2 套接字没有“刷新”功能。 如果您需要快速连续发送两条消息,则只需发送它们。 如果它是 TCP 套接字,那么它们将以正确的顺序(您发送它们的顺序)到达。 这种模式实际上并不少见; 首先发送消息头,然后单独发送消息数据。 回答3 以 Winsock 常见问题中的示例为您的数据包方案问题的准确答案 回答4 据我所知
  • How to recive more than 65000 bytes in C++ socket using recv()
    I am developing a client server application (TCP) in Linux using C++. I want to send more than 65,000 bytes at the same time. In TCP, the maximum packet size is 65,535 bytes only. How can I send the entire bytes without loss? Following is my code at server side. //Receive the message from client socket if((iByteCount = recv(GetSocketId(), buffer, MAXRECV, MSG_WAITALL)) > 0) { printf("\n Received bytes %d\n", iByteCount); SetReceivedMessage(buffer); return LS_RESULT_OK; } If I use MSG_WAITALL it takes a long time to receive the bytes so how can I set the flag to receive more than 1 million
  • 通过 TCP 套接字发送字符缓冲区不完整(Sending char buffer through TCP socket incomplete)
    问题 我只是在学习如何在 C 中处理套接字和 TCP 连接。我有一个应用程序(一个很长的应用程序),它基本上通过从服务器到客户端的系统调用 write 来发送和接收字符数组,反之亦然(两个单独的 C 应用程序当然)。 只要我将它与本地连接一起使用,在同一台 PC 上,在终端上运行服务器,在另一个终端上运行客户端,一切正常,数据到达目的地。 但是,如果我在一台计算机上的服务器和另一台计算机上的客户端尝试它,但在同一条互联网线路上,向客户端传递一个地址,如 192.168.1.X(从运行服务器的机器上获取),在连接建立后,我收到一个错误,告诉我预期的字节数(我在发送真正的 char[] 之前通过)未到达。 如果我在我的 PC 上尝试服务器,而在另一台具有不同提供商的不同线路的客户端上尝试同样的事情。 我遗漏了一些东西,按顺序发送一堆字节有什么限制吗? 错误弹出的代码。 服务器端: r=htonl(lghstr); w=write(myFd,&r,sizeof(int));//writes the number of incoming bytes if(w<0) perror("writeServer4"),exit(-1); w=write(myFd,tmp->string,lghstr); if(w<0) perror("writeServer5"),exit(-1); if(w
  • Python套接字接收-传入的数据包始终具有不同的大小(Python socket receive - incoming packets always have a different size)
    问题 我正在将SocketServer模块用于TCP服务器。 我在这里遇到了recv()函数的问题,因为传入的数据包总是具有不同的大小,因此,如果我指定recv(1024) (我尝试使用更大的值,并且更小),则它在2或2之后卡住。 3个请求,因为数据包长度将变小(我认为),然后服务器被卡住直到超时。 class Test(SocketServer.BaseRequestHandler): def handle(self): print "From:", self.client_address while True: data = self.request.recv(1024) if not data: break if data[4] == "\x20": self.request.sendall("hello") if data[4] == "\x21": self.request.sendall("bye") else: print "unknow packet" self.request.close() print "Disconnected", self.client_address launch = SocketServer.ThreadingTCPServer(('', int(sys.argv[1])),Test) launch.allow_reuse_address
  • Multipe Send() 和 Recv() 使用 Winsock2(Multipe Send()'s and Recv()'s using Winsock2)
    问题 我正在使用 Winsock2 进行一个小型网络项目。 我正在使用 TCP 连接,实际上正在使用 IRC 作为示例,因为 IRC 相当简单。 我正在做的是连接到服务器并发送一个初始缓冲区,以便服务器识别连接。 这工作正常。 我担心的是我无法再次写入套接字。 如果我在发送初始缓冲区后不使用 shutdown()(在 SD_SEND 上),我的程序似乎会挂起。 所以我要发送的下一个数据(基于 RFC 1459)是 USER 和 NICK 信息,但是,我觉得使用 shutdown() 是导致我当前问题的原因。 有没有办法重新初始化写套接字? 谢谢! 添加代码 请注意,这些位于一个类中,因此它仍然可能会被略微遮挡。 我正在使用我拥有的元素将它写成一个更简单的例子。 一切都被正确定义,所以如果我忘记定义东西,我很抱歉,但是我的许多重复变量都是为类的范围定义的。 int main(int argc,char *argv[]) { int iResult; SOCKET Connection; iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if(iResult != 0) throw "Startup failed!"; // Prep stuff ZeroMemory(&hints,sizeof(hints)); // This struct
  • TCP/IP,UDP通信——C++实现
    整理TCP/IP UDP通信的相关知识点和内容 目录 基于TCP(面向连接)的socket编程 基于UDP(面向无连接)的socket编程 TCP/IP 服务端与客户端示例 UDP 服务端与客户端示例 基于UDP的简单的聊天窗口 过程中,遇到的问题: 解决方案: 基于TCP(面向连接)的socket编程 服务器端程序: 创建套接字(socket)将套接字绑定到一个本地地址和端口上(bind):目的是为了告诉客户端,服务器准备在哪个ip地址哪个端口接受请求。将套接字设置为监听模式,准备接收客户端请求(listen)等待客户端请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。接收客户端请求后,就保存了客户端的IP和端口号。用返回的套接字 ,与客户端进行通信(send/recv)当不需要的时候,关闭套接字(closesocket) 客户端程序: 创建套接字(socket)向服务器发出连接请求(connect)和服务器端进行通信(send/recv)关闭套接字(closesocket) 运行时,服务器端先启动。 基于UDP(面向无连接)的socket编程 服务器端(接收端)程序: 创建套接字(socket)将套接字绑定到一个本地地址和端口上(bind):告诉客户端,服务器端在哪个端口哪个IP上等待数据。等待接收数据(recvfrom/sendto
  • Multipe Send()'s and Recv()'s using Winsock2
    I am working on a small networking project using Winsock2. I am using a TCP connection and actually am working with IRC as an example since IRC is fairly simple. What I am doing is connecting to the server and sending an initial buffer so the server recognizes a connection. This works fine. What concerns me is that I cannot write to the socket again. It seems my program hangs if I do not use shutdown() (on SD_SEND) after I send the initial buffer. So the next data (based on RFC 1459) I want to send is the USER and NICK information, however, I feel like using shutdown() is what is causing my
  • 如何检查是否使用 Python 中的 TCP 套接字接收到所有数据(How to check if all data are received with a TCP Socket in Python)
    问题 我正在尝试使用 Python 作为编程语言从 TCP 连接(仅限客户端)获取数据, 但是,我可以看到所有数据都不是一次接收到的,而是在接收过程的中间被截断了......我在论坛上看到 TCP 没有以正确的顺序发送数据(有点随机,链接: Python 套接字接收 - 传入的数据包总是有不同的大小),我错了吗? 我的问题是是否有办法确保我正确接收了所有数据? 预先感谢您的帮助和回复, PS:我已经增加了 socket.recv() 的缓冲区大小,但仍然面临同样的问题......而且我只在 CentOS 下工作 编辑:(无法回答我自己的问题 :( 在这个论坛上仍然是初学者 :) ) 你好, 非常感谢您的回复,确实不用担心 TCP 连接了 :) 经过更多的调查,我终于找到了解决方案......(我在这里发布我的问题之前搜索了几天), 如果有人需要答案,在python中你必须等待完整的消息,否则消息可以被截断,所以这意味着: data = s.recv(1024, socket.MSG_WAITALL) --> 's'是python代码中创建的socket对象, 亲切的问候 回答1 使用套接字 API,您不必担心 TCP(排序、重传等),这一切都由操作系统处理。 唯一的问题是socket.recv()最多返回 n 个字节。 这意味着不能保证您在每次阻塞读取时都会收到 n 个字节。 因此
  • How to check if all data are received with a TCP Socket in Python
    I am trying to get data from a TCP Connection (client side only) using Python as programming language, However, I could see that all data are not received in once and are cut in the middle of the receiving process ... I could see on forums that TCP does not send data in the correct order (it is a bit random, link: Python socket receive - incoming packets always have a different size), am I wrong ? My question is if there is anyway to make sure that I correctly received all data? Thanks in advance for your help and replies, PS: I already increased the buffer size of socket.recv(), but still
  • 无法从套接字读取(挂起)(Can't read from socket (hangs))
    问题 我正在使用 PHP 连接到本地 C++ 套接字服务器,以在 Web 应用程序和几个守护程序之间保持状态。 我可以将数据发送到套接字服务器,但不能从中接收; 它只是阻塞socket_read()并无限期挂起。 我是否忘记了一些愚蠢的东西(例如 NULL 字符或换行符的不同组合)? PHP如下: socket_connect($sock, $addr, $port); socket_write($sock, 'Hello world'); $str = ''; while($resp = socket_read($sock, 1000)) $str .= $resp; socket_close($sock); die("Server said: {$str}"); 套接字服务器的相关部分如下(注意<<和>>运算符已重载): std::string data; sock >> data; sock << data << std::endl; 其中>>调用Socket::recv(std::string&)和>>调用Socket::send(const std::string&) 。 这在(例如)telnet 上运行良好,但 PHP 不想玩得很好。 任何想法/建议表示赞赏。 回答1 Sockets in PHP, as in most programming languages
  • C++ 实现简单Tcp服务器端 -- 多线程方式(包含客户端)
    一个简单的聊天服务器端程序,多线程设计,针对多客户端。windows平台 服务器: #include <WinSock2.h> #include <WS2tcpip.h> #include <iostream> using namespace std; #pragma comment(lib, "ws2_32.lib") //一个简单的聊天程序 针对多客户端 //stdcall 的线程处理函数 DWORD WINAPI ThreadFun(LPVOID lpThreadParameter); int main() { //加载winsock2的环境 WSADATA wd; if(0 != WSAStartup(MAKEWORD(2, 2), &wd)) { cout << "WSAStartup error : " << GetLastError() << endl; return 0; } //1. 创建流式套接字 SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == s) { cout << "socket error : " << GetLastError() << endl; return 0; } //2. 绑定端口和Ip sockaddr_in addr; addr.sin
  • c++之网络编程
    TCP和UDP属于传输层协议。其中TCP提供IP环境下的数据可靠传输,它事先为要发送的数据开辟好连接通道(三次握手),然后再进行数据发送;而UDP则不为IP提供可靠性,一般用于实时的视频流传输,像rtp、rtsp就是建立在udp的基础上的。 本文参考基于TCP/IP的网络编程(C++语言编程) 注意关闭安全开发生命周期(SDL)。 基于TCP 基本思路: 服务端: 1、加载socket库(WSADATA wsdata;) 2、创建socket套接字(socket函数) 3、分配IP地址和端口号(bind函数) 4、监听可接收请求状态(listen函数) 5、接收客户端连接请求(accept函数) 6、开始传输数据(recv/send函数) 7、关闭套接字(closesock函数) 客户端: 1、加载socket库(WSADATA wsdata;) 2、创建socket套接字(socket函数) 3、初始化客户端和服务端的地址包 4、与服务器创建连接(connect函数) 5、开始传输数据(send/recv函数) 6、关闭套接字(closesock函数) server.cpp #include<stdio.h> #include<stdlib.h> #include<iostream> #include<cstring> #include<WinSock2.h> //链接ws2
  • MinGW通过Socket网页资源下载(C++简单网络爬虫)
    需求 MinGW编程编译工具 #include “winsock2.h” #pragma comment(lib,“ws2_32.lib”) 这两个是windows上网络访问时C++必需的头文件和库文件 代码 C++的Socket访问网页的机制分得比较细,不像其它编程语言能直接访问,步骤较多。 #include "winsock2.h" #include <string> #include <iostream> #include <fstream> #pragma comment(lib,"ws2_32.lib") using namespace std; int main(void) { string url = "www.baidu.com"; int port = 80; //这是启动网络访问功能 WSADATA wsa; WSAStartup(2, &wsa); //1.建立socket,socket是应用层必经网络访问虚拟层 int tcp_socket = socket(AF_INET, SOCK_STREAM, 0); //2.主网页URl转化下面 sockaddr_in用 struct hostent * hp = ::gethostbyname(url.c_str()); //访问地址 struct sockaddr_in saddr; saddr.sin
  • 为 posix recv 设置超时会导致丢失 udp 数据包吗?(Can setting a timeout for posix recv cause lost udp packets?)
    问题 我找到了有关如何为 posix 套接字设置超时的答案。 该答案的 linux 部分: // LINUX struct timeval tv; tv.tv_sec = timeout_in_seconds; tv.tv_usec = 0; setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); 以及来自 posix 文档的引用: SO_RCVTIMEO 设置超时值,该值指定输入函数在完成之前等待的最长时间。 它接受带有秒数和微秒数的 timeval 结构,指定等待输入操作完成的时间限制。 如果接收操作阻塞了这么长时间而没有接收到额外的数据,如果没有接收到数据,它应该返回一个部分计数或设置为 [EAGAIN] 或 [EWOULDBLOCK] 的 errno。 此选项的默认值为零,表示接收操作不会超时。 此选项采用 timeval 结构。 请注意,并非所有实现都允许设置此选项。 我不明白的是:这会导致丢失 udp 包吗? 收到udp包时超时怎么办? 还相关:为 UDP 套接字的 recv fcn 设置超时 PS:我知道 UDP 本质上是不可靠的,所以我的问题主要是关于在处理 udp 消息时发生超时的情况。 回答1 不; 它不会让你更有可能丢包。 查看网络传输如何在较低级别发生; 你有网卡。
  • Winsock2 - How to use IOCP on client side
    I’ve recently started learning IOCP on Windows and been reading the following article: http://www.codeproject.com/Tips/95363/Another-TCP-echo-server-using-IOCP You can download the sample for the article from: http://dl.dropbox.com/u/281215/documentation/iocp-1.00.html The sample contains two simple applications – iocp_echo_server and TcpEchoClient. I understand that IOCP is usually used on the server side of the client/server model but I’d like to create a client using IOCP. I’ve so far tried modifying the client sample above so that whenever the server sends a response to the client, it gets
  • Winsock2 - 如何在客户端使用 IOCP(Winsock2 - How to use IOCP on client side)
    问题 我最近开始在 Windows 上学习 IOCP 并阅读了以下文章: http://www.codeproject.com/Tips/95363/Another-TCP-echo-server-using-IOCP 您可以从以下位置下载本文的示例: http://dl.dropbox.com/u/281215/documentation/iocp-1.00.html 该示例包含两个简单的应用程序—— iocp_echo_server和TcpEchoClient 。 我知道 IOCP 通常用于客户端/服务器模型的服务器端,但我想使用 IOCP 创建一个客户端。 到目前为止,我已经尝试修改上面的客户端示例,以便每当服务器向客户端发送响应时,它都会自动获取,但是它不起作用。 我保留了 iocp_echo_server.c 原样。 我修改后的 TcpEchoClient.c 版本如下所示: //TcpEchoClient.c - a minimalistic echo client // ----------------------------------------------------------------------------- // C language includes #include <stdio.h> #include <winsock2.h> #include
  • 如何在 PHP 中获取此函数 socket_recv() 的最大长度(how to get maximum length of this function socket_recv() in PHP)
    问题 if(socket_recv ( $sock , $buf , 2045, MSG_WAITALL ) === FALSE) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Could not receive data: [$errorcode] $errormsg <br>"); } echo $buf; 从上面的函数它没有显示完整的消息,所以我试图像这样获得变量 $buf 的最大长度 socket_recv ( $sock , $buf , strlen($buf), MSG_WAITALL ) 但不工作。 请帮助我 谢谢和问候, 回答1 您应该收到带有循环的响应 $received; while(socket_recv($sock, $buf, 1024, 0) >= 1) { $received .= $buf; }