DNA图谱 / 问答 / 问答详情

非阻塞的socket为什么发送和接收的数据不一致

2023-07-19 10:39:09
共1条回复
莫妮卡住了

一.发送选用send(这里特指TCP)以及sendto(这里特指UDP)来描述

首先需要说明的是,不管阻塞还是非阻塞,在发送时都会将数据从应用缓冲区拷贝到内核缓冲区(SO_RCVBUF选项声明,除非缓冲区大小为0)。我在网络上看到某些人说,阻塞就是将数据真正发送给对方,并且阻塞是发生在需要把前面的所有数据全部发送出去,然后再发送本次的,而非阻塞则是拷贝到发送缓冲区。我不得不说,上面的这种说法是错误的。

在阻塞模式下send操作将会等待所有数据均被拷贝到发送缓冲区后才会返回。

如果当前发送缓冲总大小为8192,已经拷贝到缓冲的数据为8000,那剩余的大小为192,现在需要发送2000字节数据,那阻塞发送就会等待缓冲区足够把所有2000字节数据拷贝进去,如第一次拷贝进192字节,当缓冲区成功发送出1808字节后,再把应用缓冲区剩余的1808字节拷贝到内核缓冲,而后send操作返回成功发送字节数。

从上面的过程不难看出,阻塞的send操作返回的发送大小,必然是你参数中的发送长度的大小。

在阻塞模式下的sendto操作不会阻塞。

关于这一点的原因在于:UDP并没有真正的发送缓冲区,它所做的只是将应用缓冲区拷贝给下层协议栈,在此过程中加上UDP头,IP头,所以实际不存在阻塞。

在非阻塞模式下send操作调用会立即返回。

关于立即返回大家都不会有异议。还是拿阻塞send的那个例子来看,当缓冲区只有192字节,但是却需要发送2000字节时,此时调用立即返回,并得到返回值为192。从中可以看到,非阻塞send仅仅是尽自己的能力向缓冲区拷贝尽可能多的数据,因此在非阻塞下send才有可能返回比你参数中的发送长度小的值。

如果缓冲区没有任何空间时呢?这时肯定也是立即返回,但是你会得到WSAEWOULDBLOCK/E WOULDBLOCK 的错误,此时表示你无法拷贝任何数据到缓冲区,你最好休息一下再尝试发送。

在非阻塞模式下sendto操作 不会阻塞(与阻塞一致,不作说明)。

二.接收选用recv(这里特指TCP)以及recvfrom(这里特指UDP)来描述

在阻塞模式下recv,recvfrom操作将会阻塞 到缓冲区里有至少一个字节(TCP)或者一个完整UDP数据报才返回。

在没有数据到来时,对它们的调用都将处于睡眠状态,不会返回。

在非阻塞模式下recv,recvfrom操作将会立即返回。

如果缓冲区 有任何一个字节数据(TCP)或者一个完整UDP数据报,它们将会返回接收到的数据大小。而如果没有任何数据则返回错误 WSAEWOULDBLOCK/E WOULDBLOCK。

以上是关于阻塞非阻塞发送接收的区别以及在缓冲区处理上的差别,希望给看到这篇文章的人一些帮助。同时也想纠正网络上的某些错误观点,文章中表述如有错误,望大家指正,谢谢。

相关推荐

recvfrom函数

  recvfrom函数用于从(已连接)套接口上接收数据,并捕获数据发送源的地址。  本函数用于从(已连接)套接口上接收数据,并捕获数据发送源的地址。  对于SOCK_STREAM类型的套接口,最多可接收缓冲区大小个数据。如果套接口被设置为线内接收带外数据(选项为SO_OOBINLINE),且有带外数据未读入,则返回带外数据。应用程序可通过调用ioctlsocket()的SOCATMARK命令来确定是否有带外数据待读入。对于SOCK_STREAM类型套接口,忽略from和fromlen参数。  对于数据报类套接口,队列中第一个数据报中的数据被解包,但最多不超过缓冲区的大小。如果数据报大于缓冲区,那么缓冲区中只有数据报的前面部分,其他的数据都丢失了,并且recvfrom()函数返回WSAEMSGSIZE错误。  若from非零,且套接口为SOCK_DGRAM类型,则发送数据源的地址被复制到相应的sockaddr结构中。fromlen所指向的值初始化时为这个结构的大小,当调用返回时按实际地址所占的空间进行修改。  如果没有数据待读,那么除非是非阻塞模式,不然的话套接口将一直等待数据的到来,此时将返回SOCKET_ERROR错误,错误代码是WSAEWOULDBLOCK。用select()或WSAAsynSelect()可以获知何时数据到达。  如果套接口为SOCK_STREAM类型,并且远端“优雅”地中止了连接,那么recvfrom()一个数据也不读取,立即返回。如果立即被强制中止,那么recv()将以WSAECONNRESET错误失败返回。
2023-07-18 16:08:392

python设计UDP通信时,recvfrom()中的参数是什么意思

socket.recvfrom(bufsize[, flags])Receive data from the socket. The return value is a pair (bytes, address) where bytes is a bytes object representing the data received and address is the address of the socket sending the data. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero. (The format of address depends on the address family — see above.)recvfrom(1)就是从缓冲区读一个字节的数据
2023-07-18 16:08:481

recvfrom()的一次调用只能返回一个UDP包。此种说法正确吗?

1.一次recvfrom()调用只能返回一个UDP数据包。 2.send()函数参数中的buffer长度有限制,此长度限制取决于底层协议的数据包最大长度,这个长度可以通过getsockopt函数设置SO_MAX_MSG_SIZE参数获得,如果发送的数据包超过底层协议的最大长度则返回WSAEMSGSIZE错误,同时不发送任何数据。 sendto()函数参数中的buffer长度也有限制,这个限制更明显一些,数据包的数据部分(不包括数据头)的长度不能超过512字节。 3.send()与sendto()正常返回均不能保证发送的数据被接受方正确接收,还要看缓冲区是否已满。当缓冲区为空时,recv与recvfrom均阻塞等待(除非设置为非阻塞,此时将返回WSAEWOULDBLOCK错误),因此只要socket正常连接,且缓冲区有数据内容,recv与recvfrom函数虽延迟但均能正常接收数据包。 希望我的回答你能满意:) 你好,我看了你添加的内容,我上面所说的最大长度512字节是指UDP数据包可以发送的的最大长度,针对的是sendto函数,而你测试时使用的则是TCP连接中的send函数,两者使用的协议不同,因此缓冲区的长度当然不同了,我使用getsockopt测试,得到我本机接受方的最大缓冲为8192字节,测试代码如下: #include <stdio.h> #include "winsock2.h" void main() { WSADATA wsaData; SOCKET ListenSocket; sockaddr_in service; int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); if( iResult != NO_ERROR ) printf("Error at WSAStartup "); ListenSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if (ListenSocket == INVALID_SOCKET) { printf("Error at socket() "); WSACleanup(); return; } hostent* thisHost; char* ip; u_short port; 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 ) { printf("bind failed "); closesocket(ListenSocket); return; } int optVal; int optLen = sizeof(int); getsockopt(ListenSocket, SOL_SOCKET, SO_RCVBUF, (char*)&optVal, &optLen); printf("The max length is %d ", optVal); WSACleanup(); return; } 在此补充一下,上面所说SO_MAX_MSG_SIZE只针对UDP这种数据报形式的协议有效,而对于基于流的TCP/IP无效,因此在此使用SO_RCVBUF参数,如果还有问题敬请指出:)
2023-07-18 16:09:072

哪位大神帮解决一下啊?到底哪里不对啊?recvfrom返回值总是-1.

recvfrom 返回-1表示接收数据失败,一般有两种情况会失败,当接收缓冲区小于对方发送的数据时,缓冲区无法接收这个包,recvfrom失败,另外一种,传入的参数有问题,例如socketaddrlength,或者socket句柄有问题,这些都会直接返回-1,不会有任何阻塞
2023-07-18 16:09:153

对UDP套接字调用recvfrom返回0代表什么意思

若无错误发生,recv()from()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。错误代码:WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEFAULT:fromlen参数非法;from缓冲区大小无法装入端地址。WSAEINTR:阻塞进程被WSACancelBlockingCall()取消。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEINVAL:套接口未用bind()进行捆绑。WSAENOTCONN:套接口未连接(仅适用于SOCK_STREAM类型)。WSAENOTSOCK:描述字不是一个套接口。WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM类型的。WSAESHUTDOWN:套接口已被关闭。当一个套接口以0或2的how参数调用shutdown()关闭后,无法再用recv()接收数据。WSAEWOULDBLOCK:套接口标识为非阻塞模式,但接收操作会产生阻塞。WSAEMSGSIZE:数据报太大无法全部装入缓冲区,故被剪切。WSAECONNABORTED:由于超时或其他原因,虚电路失效。WSAECONNRESET:远端强制中止了虚电路。判断一下,然后对应处理就行
2023-07-18 16:09:241

如何解决recvfrom不 阻塞问题

方法1. 用setsockopt设置阻塞超时时间,recvfrom阻塞一段超时后,退出响应其他线程的消息。方法2. 主线程直接把recvfrom的socket close掉,recvfrom会报错退出。
2023-07-18 16:09:311

recvfrom()的简述

接收一个数据报并保存源地址。(这里是windows中的头文件,Linux的用法在下面的那个实例)#include <winsock.h>int PASCAL FAR recvfrom( SOCKET s, char FAR* buf, int len, int flags,struct sockaddr FAR* from, int FAR* fromlen);s:标识一个已连接套接口的描述字。buf:接收数据缓冲区。len:缓冲区长度。flags:调用操作方式。from:(可选)指针,指向装有源地址的缓冲区。fromlen:(可选)指针,指向from缓冲区长度值。
2023-07-18 16:09:381

关于recvfrom()不阻塞时的等待时间问题,请帮忙~~

推荐用非阻塞的的方式。如果非要用阻塞的方式,可以把recvfrom放在一个子线程里,recvfrom完成后子线程即退出,主线程中在启动子线程后使用WaitForSingleObject(子线程句柄,等待时间),来等待子线程退出。若等待超时子线程还没有退出,在主线程中调用closesocket,这样子线程中阻塞的recvfrom会立即返回,这样主线程就可以进行下一步的流程。
2023-07-18 16:09:562

在线程为什么recvfrom不阻塞

recvfrom()会发生阻塞,直到收到数据才会返回。调用成功返回收到数据的字节数,调用失败返回SOCKET_ERROR错误,没收到数据不等于调用失败。
2023-07-18 16:10:142

请教recv 和 recvfrom的区别

不太清楚,recv一般用于tcp,因为tcp有有链接的,在recv调用中不需要知道对方是谁。recvfrom一般用于udp,参数中可以传回对方是谁的信息。
2023-07-18 16:10:231

怎么解除recvfrom阻塞的阻塞状态

方法1. 用setsockopt设置阻塞超时时间,recvfrom阻塞一段超时后,退出响应其他线程的消息。方法2. 主线程直接把recvfrom的socket close掉,recvfrom会报错退出。
2023-07-18 16:10:333

recvfrom()的最后一个参数问题

这个就看socket 的声明吧, 都这么做没办法, 这个确实很蠢。问题2 不可以sizeof(struct sockaddr) 对于程序来说就是个常数, 你能用 &2 来代替指向2的指针么,这个不行,你说的就不行。
2023-07-18 16:10:402

【奇】udp的recvfrom

UDP本来就是这样的,不需要绑定IP,只需要绑定一个端口,Sendto函数会附带IP信息,recv的时候会解析进来连接的地址。因为udp没有固定的连接,所以不知道进来的连接的IP,只能通过recv函数去实时获取,这是UDP最基本的机制。
2023-07-18 16:10:472

请问C++下recvfrom如何使用?

最近测试程序中一直在用,给你点代码片段(1) sockaddr_in from; int from_len = sizeof(from); int rc = recvfrom(sock, buf, 65536, 0, (sockaddr*)&from, &from_len); if (rc > 0) { //处理收到的数据 }(2)memset(buf, 0, BUF_SIZE);int rc = recvfrom(pThis->m_udpSocket, buf, BUF_SIZE, 0, (sockaddr*)&from, &from_len);if (rc > 0){ }
2023-07-18 16:10:542

recvfrom为什么一直被阻塞

方法1. 用setsockopt设置阻塞超时时间,recvfrom阻塞一段超时后,退出响应其他线程的消息。 方法2. 主线程直接把recvfrom的socket close掉,recvfrom会报错退出。
2023-07-18 16:11:011

客户端的接受线程recvfrom 不阻塞 为什么

方法1. 用setsockopt设置阻塞超时时间,recvfrom阻塞一段超时后,退出响应其他线程的消息。 方法2. 主线程直接把recvfrom的socket close掉,recvfrom会报错退出。
2023-07-18 16:11:081

send和sendto的区别

sendto可以在参数中指定发送的目标地址,send需要socket已建立连接,sendto可用于无连接的socket对于有连接的socket,两者一样,sendto最后两个参数没用
2023-07-18 16:11:173

recvfrom总是返回-1,怎么获取错误码?(非阻塞)

先确保 addrLen初始化了
2023-07-18 16:11:243

recvfrom()中,接受字符串大小的问题

在执行recvfrom(socket,recvbuf,strlen(recvbuf),0,(SOCKADDR*)&addrFrom,&len);之前,recvbuf里面的值根本还不确定,strlen(recvbuf)怎么会计算得对呢
2023-07-18 16:11:431

udp的recvfrom函数,能接收指定ip和端口发送来的数据吗?

不能,他的参数是用来存储发送数据的socket的。可以在接收到数据以后进行判断,如果是需要的IP则采用数据,否则丢弃数据。
2023-07-18 16:11:522

C语言下socket的recvfrom函数问题

视SOCKET是否阻塞而定,如果是阻塞的则会卡住,如果非阻塞则会立即返回。
2023-07-18 16:11:591

在c++ builder中,调用recvfrom()问题

这个是阻塞Socket,意味着如果没有其他程序给你发送数据,那么这个函数会一直停在这里,直到有数据接收到为止。
2023-07-18 16:12:131

recvfrom函数返回值问题

UDP 本来就是不可靠传输协议, 它只负责发送,不管对方有没有收到而TCP协议正好解决上述问题,它是可靠传输协议,三次握手能确保每一个数据包收到!
2023-07-18 16:12:221

怎么确保socket通信只有一次且正确

用socket实现进程通信,和socket的普通用法一样,只不过服务端IP为127.0.0.1而已下面附上代码示例://服务器端代码进程1#include#include#include#include#include#include#include#includeintmain(intargc,char*argv[]){intsock;//sendto中使用的对方地址structsockaddr_intoAddr;//在recvfrom中使用的对方主机地址structsockaddr_infromAddr;intrecvLen;unsignedintaddrLen;charrecvBuffer[128];sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);if(sock#include#include#include#include#include#include#includeintmain(intargc,char*argv[]){if(argc<2){printf("请输入要传送的内容. ");exit(0);}intsock;//sendto中使用的对方地址structsockaddr_intoAddr;//在recvfrom中使用的对方主机地址structsockaddr_infromAddr;unsignedintfromLen;charrecvBuffer[128];sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);if(sock<0){printf("创建套接字失败了. ");exit(1);}memset(&toAddr,0,sizeof(toAddr));toAddr.sin_family=AF_INET;toAddr.sin_addr.s_addr=inet_addr("127.0.0.1");toAddr.sin_port=htons(4000);if(sendto(sock,argv[1],strlen(argv[1]),0,(structsockaddr*)&toAddr,sizeof(toAddr))!=strlen(argv[1])){printf("sendto()函数使用失败了. ");close(sock);exit(1);}fromLen=sizeof(fromAddr);if(recvfrom(sock,recvBuffer,128,0,(structsockaddr*)&fromAddr,&fromLen)<0){printf("()recvfrom()函数使用失败了. ");close(sock);exit(1);}printf("recvfrom()result:%s ",recvBuffer);close(sock);}
2023-07-18 16:12:291

linux下设置recvfrom为非阻塞

可以使用1 select pselect2 poll3可以使用fcntl给文件描述符添加O—UNBLOCK
2023-07-18 16:12:361

php中socket_recvfrom

参数不全,该函数原型定义如下int socket_recvfrom ( resource $socket , string &$buf , int $len , int $flags , string &$name [, int &$port ] )至少5个参数,而你只给了一个,所以出错了
2023-07-18 16:12:441

网络程序设计UDP客户端实验问题,不管怎么调试都出现recvfrom() Failed:10054,望解决,谢谢!

10054是“连接被重置”你确定一下你发送数据包的目的端点是不是有在监听这个端口,如果没有,那么对方主机会发一个代表错误的数据包过来,然后你的recvfrom就失败了(返回-1)
2023-07-18 16:12:522

Linux下的recvfrom为什么一直阻塞

UDP的client端是需要bind的,server端不需要bind,关于阻塞的问题,应该在于你的socket的属性,设置成O_NONBLOCK就可以了。
2023-07-18 16:13:101

UDP中recvfrom函数为什么不阻塞

没开服务器执行客户端recvfrom确实返回SOCKET_ERROR。WSAGetLastError返回值10054(WSAECONNRESET )A existing connection was forcibly closed by the remote host. 看来sendto函数发送失败(IP地址无接收端口),导致recvfrom的失败。
2023-07-18 16:13:171

如何设置socket的connect recvfrom 超时

1.首先将标志位设为Non-blocking模式,准备在非阻塞模式下调用connect函数2.调用connect,正常情况下,因为TCP三次握手需要一些时间;而非阻塞调用只要不能立即完成就会返回错误,所以这里会返回EINPROGRESS,表示在建立连接但还没有完成。3.在读套接口描述符集(fd_set rset)和写套接口描述符集(fd_set wset)中将当前套接口置位(用FD_ZERO()、FD_SET()宏),并设置好超时时间(struct timeval *timeout)4.调用select( socket, &rset, &wset, NULL, timeout )返回0表示connect超时如果你设置的超时时间大于75秒就没有必要这样做了,因为内核中对connect有超时限制就是75秒。
2023-07-18 16:13:362

linux Ubuntu 中,写了一个简单的UDP协议,只用了sendto 与recvfrom ,出错了

在百度的编辑选项里面有可以写代码的,最起码代码格式整齐,容易阅读。客户端的serv_addr.sin_addr.s_addr=INADDR_ANY这里使用服务器的固定地址试试。广播模式这个地址好像是用255.255.255.0的(局域网下)。
2023-07-18 16:14:041

bind操作不会阻塞

bind操作不会阻塞,如果阻塞只可能是你程序写的有问题。
2023-07-18 16:14:111

recvfrom如果没接收到数据返回值是什么

检查,接收socket有没有绑定端口,绑定的哪个端口,这个端口,是不是客户端发送指定的端口相同。其次,检查发送的socket所发送到的地址是不是正确的,端口是不是正确。再次次,sendto是UDP的发送接口,UDP不提供有保证的服务(与TCP的不同)。所以,在网络状况差的环境下,UDP很有可能会丢包。如果楼主要传输文件之类的数据,建议使用TCP,因为文件需要保证完整性,UDP可能会丢包。保证不了。当然,你也可以添加RTP协议辅助UDP来保证传输。
2023-07-18 16:14:182

手机总出现recvfrom failed: ECONNRESET (Connection reset by peer) 怎么解决?

Java代码 ### The error occurred while setting parameters ### SQL: insert into SYS_SECURITY_RIGHT_SYSTEM( SYSRIGHT_ID, SYS_ORDER, SYS_NAME, SYS_MEMO ) values ( ?, ?, ?, ? ) ### Cause: java.sql.SQLException: ORA-01400: 无法将 NULL 插入 ("SMARTCITY"."SYS_SECURITY_RIGHT_SYSTEM"."SYSRIGHT_ID") ] 在使用Mybatis主键自增长时,其要求使用Integer,使用〈selectKey〉时需要数据库中存在一条数据,不然回报上述错误。 Java代码 2013-06-19 09:27:56,109 [http-bio-8080-exec-1] DEBUG [org.mybatis.spring.SqlSessionUtils] - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1681460] 2013-06-19 09:27:56,119 [http-bio-8080-exec-1] DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [org.apache.commons.dbcp.PoolableConnection@a1e9b0] will be managed by Spring 2013-06-19 09:27:56,119 [http-bio-8080-exec-1] DEBUG [dci.smartcity.operationsmanagement.dao.IOrgDAO.update] - ooo Using Connection [org.apache.commons.dbcp.PoolableConnection@a1e9b0] 2013-06-19 09:27:56,129 [http-bio-8080-exec-1] DEBUG [dci.smartcity.operationsmanagement.dao.IOrgDAO.update] - ==> Preparing: update SYS_SECURITY_ORG SET ORG_NAME= ?, ORG_PID=?, ORG_ORDER=?, ORG_MEMO=?, ORG_CREATETIME=?, ORG_CREATEUSER=? where ORG_ID = ? 2013-06-19 09:27:56,129 [http-bio-8080-exec-1] DEBUG [dci.smartcity.operationsmanagement.dao.IOrgDAO.update] - ==> Parameters: xx (String), 1(Integer), 2(Integer), dfd (String), 20121111(Integer), ??????? (String), 3(Integer) 2013-06-19 09:27:56,156 [http-bio-8080-exec-1] DEBUG [org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator] - Unable to translate SQLException with Error code "12899", will now try the fallback translator 2013-06-19 09:27:56,159 [http-bio-8080-exec-1] DEBUG [org.springframework.jdbc.support.SQLStateSQLExceptionTranslator] - Extracted SQL state class "72" from value "72000" 2013-06-19 09:27:56,161 [http-bio-8080-exec-1] DEBUG [org.mybatis.spring.SqlSessionUtils] - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1681460]
2023-07-18 16:14:271

C/C++ 网络程序中用select()检查套接字可读性,有哪几种可能使recvfrom()调用的套接字无可读性

这里的超时值设置在select的最后一个参数里,设置为NULL表示一直等下去。我估计你设置的receive的超时值,所以这里不起作用(不知道对不对)。至于为什么接受不到数据,那就是其他方面的原因了,有可能是根本没有数据到达,而你又设置一直等下去,所以select一直阻赛。你可以看看<<unix网络编程>>P.137 记住了,select函数的参数是一个值-结果参数,他每次返回的时候都会把与描述字集中未就绪的描述字位相对应的位清0,也就是说如果select发现该描述字没有准备好,就把他对应的位清0,所以每次调用select的时候都要重新设置我们关心的位为1。
2023-07-18 16:14:342

SocketException:recvfromfailed:ECONNRESET是什么意思

package com.ucaimalls.util; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import android.util.Log; /** * 网络连接类 */ public class HttpHelper { public static final int TIME_OUT_MILL = 10000;// 超时毫秒数 /** * HttpURLConnection 请求方式,直接返回字符串数据 */ public static String getHttpUrlConnData(String url) throws Exception { URL realUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection(); conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"); conn.setDoOutput(true); conn.setDoInput(true); conn.setConnectTimeout(TIME_OUT_MILL); conn.setReadTimeout(TIME_OUT_MILL); InputStream is = conn.getInputStream(); ByteArrayOutputStream dis = new ByteArrayOutputStream(); int realRead = 0; byte[] buff = new byte[1024]; while ((realRead = is.read(buff )) != -1) { dis.write(buff,0,realRead); } String data = new String(dis.toByteArray(), "UTF-8").trim(); // System.out.println(data); if (dis != null) { dis.close(); } if(conn!=null) { conn.disconnect();//断开连接---问题产生的原因了 } return data; } } ok, the answer was that it"s the server"s fault - it had to close the connection after each request .it might be that android keeps a pool of connections and use the old one or something like that .anyway , now it works.EDIT: according to the API of HttpURLConnection , this can be solved on the client side too:The input and output streams returned by this class are not buffered. Most callers should wrap the returned streams with BufferedInputStream or BufferedOutputStream. Callers that do only bulk reads or writes may omit buffering. When transferring large amounts of data to or from a server, use streams to limit how much data is in memory at once. Unless you need the entire body to be in memory at once, process it as a stream (rather than storing the complete body as a single byte array or string).To reduce latency, this class may reuse the same underlying Socket for multiple request/response pairs. As a result, HTTP connections may be held open longer than necessary. Calls to disconnect() may return the socket to a pool of connected sockets. This behavior can be disabled by setting the http.keepAlive system property to false before issuing any HTTP requests. The http.maxConnections property may be used to control how many idle connections to each server will be held.
2023-07-18 16:14:421

recv()和recvfrom()有什么区别?

对于recvfrom 可同时应用于面向连接的和无连接的套接字。recv一般只用在面向连接的套接字,几乎等同于recvfrom,只要将recvfrom的第五个参数设置NULL。说白了就是 recvfrom比recv多了一个导航功能,你看名字就很好理解啦,有个from吗
2023-07-18 16:15:094

python设计UDP通信时,recvfrom()中的参数是什么意思?

socket.recvfrom(bufsize[, flags])Receive data from the socket. The return value is a pair (bytes, address) where bytes is a bytes object representing the data received and address is the address of the socket sending the data. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero. (The format of address depends on the address family — see above.)recvfrom(1)就是从缓冲区读一个字节的数据
2023-07-18 16:15:491

socket 编程中 recvfrom没有收到udp包(如网络不通时),怎么让它返回?

若无错误发生,recvfrom()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。 错误代码: WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。 WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。 WSAEFAULT:fromlen参数非法;from缓冲区大小无法装入端地址。 WSAEINTR:阻塞进程被WSACancelBlockingCall()取消。 WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。 WSAEINVAL:套接口未用bind()进行捆绑。 WSAENOTCONN:套接口未连接(仅适用于SOCK_STREAM类型)。 WSAENOTSOCK:描述字不是一个套接口。 WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM类型的。 WSAESHUTDOWN:套接口已被关闭。当一个套接口以0或2的how参数调用shutdown()关闭后,无法再用recv()接收数据。 WSAEWOULDBLOCK:套接口标识为非阻塞模式,但接收操作会产生阻塞。 WSAEMSGSIZE:数据报太大无法全部装入缓冲区,故被剪切。 WSAECONNABORTED:由于超时或其他原因,虚电路失效。 WSAECONNRESET:远端强制中止了虚电路。判断一下,然后对应处理就行
2023-07-18 16:15:561

recvfrom函数得到的IP地址为什么不对?

while(1){ recvfrom(sockfd, readbuff, UDP_CMD_BUFF_LENGTH - 1, 0, (struct sockaddr *)&Glob_remot_88_port_add, &len); PRINT("[recevudp]len %d IP is %s ", len, inet_ntoa(Glob_remot_88_port_add.sin_addr));}这个函数, 第一次接受打印出的发送方IP地址总是0.0.0.0;解决方法:在recvfrom之前加一句: len = sizeof(struct sockaddr);即可
2023-07-18 16:16:042

如何用sendto()发送并用recvfrom()接受结构体数据 基于MFC

你应该已经会发送普通字符串了。char *buf = new buf[1000];int length = sizeof(obj); // obj是对象,也就是你说的结构体strncpy(buf, (const char*)&obj, length); // 复制n个字节,也可以自己写个函数sendto ... .. //和发送普通字符串一样
2023-07-18 16:16:101

send sendto recv recvfrom有什么区别

send,send to和receive,receive from区别在于中心词不同区别一 代表意义send ... to  把 ... 送到 ... 去vt.发送;派遣;使处于...的状态;放出;运输vi.差遣;发出;传送receive v.接到;收到;接待receive fromv.收到区别二 中心词send,send to的中心词是送东西的人 receive,receive的中心词是接受东西的人区别三 常用句型I"ll send the maid round to carry it to your house.我将派女仆把它送到你家去。It will send you standard form for you to fill out.它(商标局)会寄给你标准表格要你填写。I want to send away for some books I need.我想发函购买我需要的一些书籍。He wired (to) his brother to send some money.他给他哥哥打了个电报要求寄些钱来。I received a cable from New York.我收到一封从纽约来的电报。We receive a fax of the order this morning.我们今天上午收到一份传真订单。
2023-07-18 16:16:171

recvfrom failed怎么解决的

可以按照以下方法:1、设置—电源--(按住shift键点击重启)--疑难解答--backup and Recovery;2、系统将会自动检查,看看智能修复选项可以解决这个问题, 一旦完成单击Next ;3、会看到选择出厂镜像文件或是其他的备份文件中的一个,当然这个地方选择的是出厂镜像文件,点next下一步;4、系统将提示备份你的文件,如果需要通过选择选项是的,备份我的个人文件(确保有一个外部备份硬盘),或选择不,抹去我的文件,再点next下一步;5、到这一步,恢复步骤就完成了,过程大约10-15分钟!
2023-07-18 16:16:251

你好,我建了两个socket,端口不同,但是有一个recvform接收不到数据,请问应该怎样修改?

不知道哪里不对...你对比一下.看有没有缺的吧#include <stdio.h>#include <string.h>#include <Winsock2.h>#include <ws2tcpip.h>#pragma comment(lib, "Ws2_32.lib")typedef struct SktInfoTag{ int skt; unsigned int ip; unsigned short port; char buf[2048]; int bufsize;}SktInfo;static int thread_proc( LPVOID param );SktInfo siInfo;void main(){ WSADATA wsaData; unsigned long threadflag; int ret = 0; unsigned long unblock =1; void* thrd = INVALID_HANDLE_VALUE; ret = WSAStartup(MAKEWORD(2,2), &wsaData); siInfo.ip = inet_addr("192.168.0.1"); siInfo.port = 5001; siInfo.bufsize = 2048; //创建socket siInfo.skt = socket(AF_INET, SOCK_DGRAM, 0); if( siInfo.skt == -1 ) { printf("socket create failed! "); goto END; } //非阻塞 ioctlsocket(siInfo.skt, FIONBIO, &unblock); if( 224 <= *((unsigned char*)&siInfo.ip) && *((unsigned char*)&siInfo.ip) <= 240 ) { struct sockaddr_in addr; struct ip_mreq mreq; int ttl = 127; int flag = 1; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = siInfo.port; //绑定本地接收端口 ret = bind( siInfo.skt, (struct sockaddr*)&addr, sizeof(addr)); if(ret < 0) { printf("bind socket failed! "); goto END; } memset(&mreq, 0, sizeof(mreq)); mreq.imr_multiaddr.s_addr = siInfo.ip; mreq.imr_interface.s_addr = INADDR_ANY; //设置缺省参数 setsockopt(siInfo.skt, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)); setsockopt(siInfo.skt, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)flag, sizeof(flag)); //加入组播 ret = setsockopt(siInfo.skt, IPPROTO_IP, IP_ADD_MEMBERSHIP,(char*)&mreq, sizeof(mreq)); if( ret < 0 ) { printf("setsockopt socket failed! "); goto END; } } else { struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = siInfo.ip; addr.sin_port = siInfo.port; //绑定本地接收地址端口 ret = bind(siInfo.skt, (struct sockaddr*)&addr, sizeof(addr)); if( ret < 0 ) { printf("bind socket failed! "); goto END; } } //创建接收线程 if( INVALID_HANDLE_VALUE == (thrd = CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)thread_proc, (LPVOID)&siInfo, 0, &threadflag)) ) { goto END; } while(1) { Sleep(200); }END: if( thrd != INVALID_HANDLE_VALUE ) { CloseHandle(thrd); thrd = NULL; }}int thread_proc( LPVOID param ){ fd_set rset; int ret = 0; int size = 0; SktInfo* info = (SktInfo*)&param; struct sockaddr_in from; int slen = sizeof(from); struct timeval tv; unsigned char *recvip; unsigned short *recvport; int timeout = 100; if( info->skt == -1) goto EXIT_END; tv.tv_sec = timeout/1000; tv.tv_usec = (timeout%1000)*1000; while(1) { memset(&from, 0, sizeof(from)); FD_ZERO(&rset); FD_SET(info->skt, &rset); //检测可接收 ret = select(info->skt+1, &rset, NULL, NULL, &tv); if( ret < 0 ) { goto SLEEP; }if( FD_ISSET(info->skt, &rset)) { //接收数据 size = recvfrom(info->skt, info->buf, info->bufsize, 0, (struct sockaddr*)&from, &slen); if( size <= 0 ) { goto EXIT_END; } recvip = (unsigned char*)(&from.sin_addr.S_un.S_addr); recvport = &from.sin_port; printf("recv form %d.%d.%d.%d:%d %d byte data ", recvip[0], recvip[1], recvip[2], recvip[3], ntohs(*recvip), size); }SLEEP: Sleep(5); }EXIT_END: return -1;}
2023-07-18 16:16:333

C语言 UDP中revcfrom怎么从阻塞中跳出?

在创建套接口后调用一下ioctlsocket()函数,设置为非阻塞即可,如下://UDPServer.cpp#pragma comment(lib,"ws2_32.lib")#include<winsock2.h>#include<stdio.h>#include<string.h>int main(){ WSADATA wsaData; int err = WSAStartup(WINSOCK_VERSION,&wsaData); if(err!=0) { printf("Socket start failed:%d ",err); return -1; } //创建套接口:socket() SOCKET sock; sock = socket(AF_INET,SOCK_DGRAM,0); //!!在此设置非阻塞!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! unsigned long iMode = 1;//为0时阻塞,非0时不阻塞 ::ioctlsocket(sock,FIONBIO,&iMode); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if(sock==INVALID_SOCKET) { printf("Creat socket Failed:%d ",WSAGetLastError()); WSACleanup(); return -1; } //绑定端口:bind() sockaddr_in localaddr; localaddr.sin_family = AF_INET; localaddr.sin_port = htons(8800); localaddr.sin_addr.s_addr = htonl(INADDR_ANY); //#define s_addr S_un.S_addr err = bind(sock,(sockaddr *)&localaddr,sizeof(localaddr));//调用bind()绑定端口 if(err == SOCKET_ERROR) //出错处理 { printf("Bind failed:%d ",WSAGetLastError()); closesocket(sock); WSACleanup(); return -1; } //等待接收信息 char rbuf[1024]; sockaddr_in faraddr; int farlen = sizeof(faraddr); printf("Server is startup! Waiting for message: "); //do while(true) { memset(rbuf,0,1024); //清空接收缓冲区rbuf[1024] int rByte = recvfrom(sock,rbuf,1024,0,(sockaddr *)&faraddr,&farlen);//阻塞等待 if(rByte == SOCKET_ERROR) { printf("Recvfrom failed:%d ",WSAGetLastError()); closesocket(sock); WSACleanup(); return -1; } printf("UDP Recv %d Data from %s:%s ",rByte,inet_ntoa(faraddr.sin_addr),rbuf);if(strlen(rbuf)==0) { printf("Client %s have finished! ",inet_ntoa(faraddr.sin_addr)); } }//while(strlen(rbuf)!=0);//收到空数据包,则认为对方已经发送完成 return 0;}
2023-07-18 16:16:401

WSARecvFrom()的参数

s:一个标识套接口的描述字。lpBuffers:一个指向WSABUF结构数组的指针。每个WSABUF结构包含缓冲区的指针和缓冲区的大小。dwBufferCount:lpBuffers数组中WSABUF结构的数目。lpNumberOfBytesRecvd:如果接收操作立即完成,则为一个指向所接收数据字节数的指针。lpFlags:一个指向标志位的指针。lpFrom:(可选)指针,指向重叠操作完成后存放源地址的缓冲区。lpFromlen:指向from缓冲区大小的指针,仅当指定了lpFrom才需要。lpOverlapped:指向WSAOVERLAPPED结构的指针(对于非重叠套接口则忽略)。lpCompletionRoutine:一个指向接收操作完成后调用的完成例程的指针。(对于非重叠套接口则忽略)。
2023-07-18 16:16:471

如何在VC一个函数中结束另外一个函数的运行.

你查一下msdn,recvfrom有非阻塞模式,需要设置一下socket。非阻塞模式下,recvfrom返回-1,你可以做一个while循环,来判断是否收到数据,收到数据以后再处理,没收到数据就sleep一段时间再循环。另外,从你问的问题来看,你需要补习一下windows多线程编程。 可以试着把recvfrom这个功能放到单独的线程里来做,这样即使没收到数据,线程卡死,也不会导致整个进程卡死的。但是这样一来,你又需要去多学一点线程同步的知识。让收到数据的那个线程能够告诉处理线程,有数据需要处理。有问题可以再问我,hi baidu就成。 =============更新========================单独终止一个函数的功能是没有的,但是你可以终止运行函数的线程,乃至进程,然后再重建一个线程。根据你的描述,你可以用两个线程,一个进行收udp,另一个监视这个线程,如果超过一定时间没响应,就close掉,然后再打开一个线程接收。不过这样也还是没有while + sleep的结构效果好,因为频繁的开关线程也需要浪费cpu资源的,而且不小 =============更新==========================根据你数据多少快慢来决定了。如果数据快,可以2~5ms接收一次,同时可以设置socket选项,增加接收缓存,SOCK_RECVBUF,到10M 这样基本都保证快速收报不丢。 如果不设置的话,如果短时间来了大量数据,可能会有丢数据包的情况(recvbuffer已满,而你又没有recvfrom的时候,就丢数据了)反正返回-1就是没有数据,返回>0 就有数据
2023-07-18 16:17:112

recvfrom的阻塞模式下,怎么利用多线程来实时接收并显示recvfrom收到的信息呢?

这种问题还是去CSDN上提吧。每一个线程都while循环中调用recvfrom就完了。
2023-07-18 16:17:181

UDP当recvfrom时,有没有办法知道数据是发到本地的哪个IP

检查,接收socket有没有绑定端口,绑定的哪个端口,这个端口,是不是客户端发送指定的端口相同。 其次,检查发送的socket所发送到的地址是不是正确的,端口是不是正确。 再次次,sendto是UDP的发送接口,UDP不提供有保证的服务(与TCP的不同)。...
2023-07-18 16:17:321

UDP方式recvfrom接收函数为什么有时是阻塞,而有时是非阻塞的

没开服务器执行客户端recvfrom确实返回SOCKET_ERROR。WSAGetLastError返回值10054(WSAECONNRESET )A existing connection was forcibly closed by the remote host. 看来sendto函数发送失败(IP地址无接收端口),导致recvfrom的失败。(对方机器强行关闭)请采纳。
2023-07-18 16:17:391