- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我是 Winsock 的新手。我正在编写一个 HTTP 服务器,我的目标是通过读取和发送 block 来发送一个大文件。为了优化这个过程,我尝试使用非阻塞套接字,在发送当前 block 的同时从磁盘读取下一个 block 。
我现在的问题是,即使缓冲区似乎已满并且我的函数过早地从内存中删除了相关数据,我还是收到了 FD_WRITE 消息。我相信这会导致我的响应包含的数据少于它们应该发送的数据 send() 过早地停止发送并且客户端(这是一个众所周知的)接收了大约 70% 的数据。当我使用阻塞套接字时,它工作正常,只是更长了。
我尝试使用简单的 HTTP 客户端 Wget 来更好地了解正在发生的事情。据我所知,当我在使用 send() 后检查错误时检测到 WSAEWOULDBLOCK 错误时,数据流变薄了。看起来在这些发送期间,并非所有数据都已发送。
当我在检查 FD_WRITE 消息后将 sleep 时间设置为超过 2000 毫秒时,一切正常,因为它基本上归结为使用阻塞套接字。我也尝试将时间设置为 100-200 毫秒左右,但这些也失败了。事实上,FD_WRITE 的条件检查总是在进入循环之前返回有效。
WSAEVENT event = WSACreateEvent();
const int sendBufferSize = 1024 * 64;
int connectionSpeed = 5; //estimated, in MBytes/s
const int sleepTime = sendBufferSize / (connectionSpeed * 1024 * 1024);
size = 0;
const int bufSize = 1024 * 1024 * 35;
int lowerByteIndex = 0;
int upperByteIndex = bufSize;
size = bufSize;
int totalSIZE = 0;
unsigned char* p;
unsigned char* pt;
clock_t t = std::clock();
p = getFileBytesC(resolveLocalPath(path), size, lowerByteIndex, upperByteIndex);
lowerByteIndex += bufSize;
upperByteIndex += bufSize;
totalSIZE += size;
while (upperByteIndex <= fileSize + bufSize)
{
int ret = send(socket, (char*)p, size, 0);
pt = getFileBytesC(resolveLocalPath(path), size, lowerByteIndex, upperByteIndex);
totalSIZE += size;
lowerByteIndex += bufSize;
upperByteIndex += bufSize;
if (ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
{
while (SOCKET_ERROR == WSAEventSelect(socket, event, FD_WRITE))
{
Sleep(50);
}
}
Sleep(sleepTime); //should be around 30-50ms. Wait for the buffer to be empty
delete[] p;
p = pt;
std::cout << std::endl << (std::clock() - t) / (double)CLOCKS_PER_SEC;
}
send(socket, (char*)p, size, 0);
delete[] p;
std::cout << std::endl << (std::clock() - t) / (double)CLOCKS_PER_SEC ;
if (totalSIZE == fileSize) std::cout << std::endl << "finished transfer. UBI=" << upperByteIndex;
else
{
std::cout << std::endl << "ERROR: finished transfer\r\nBytes read=" << totalSIZE;
}
Sleep(2000);
closeSocket(socket);
最佳答案
如果不将返回值存储在变量中,您就无法编写正确的非阻塞 send()
代码。它是实际发送的字节数。您不能假设整个缓冲区都是以非阻塞模式发送的。
如果 send()
返回 -1 且 WSAGetLastError() == WSAEWOULDBLOCK
或任何它是什么,那么 是时间必要时调用 WSASelect(),
或 WSAEVENTSelect()
,但要超时。否则,即如果它返回一个正计数,您应该只增加偏移量并减少发送量的长度,然后重复直到没有任何东西要发送。
你的 sleep 简直就是浪费时间。
但我会质疑整个方法。无论如何,在阻塞模式套接字上发送是异步的。您目前的方法几乎无济于事。只需以 block 的形式读取文件并以阻塞模式发送 block 。
关于c++ - 使用 send() 和 FD_WRITE 的 Winsock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32900692/
我很难理解为什么这段代码无法编译: use std::cell::{Ref, RefCell}; struct St { data: RefCell } impl St { pub f
我从Richard Blum的一本书《 C#网络编程》中读到有关套接字的信息。以下摘录指出,不保证Send()方法可以发送所有传递给它的数据。 byte[] data = new byte[1024]
我有以下程序,它必须一次读取 1MB 的文件,将其发送到服务器(每次总是 1MB)并返回哈希码: #include #include #include #include #include #
代码在底部。 第 207 行的 send() 命令本身可以正常工作。但是,当我在第 218 行添加 send() 命令时,第一个命令失败 - 给出错误“地址错误”。我已经确认第二个 send() 命令
标记包含 !Send 的类型背后的原因是什么?字段(如 Rc 或 NonNull )与 Send特征?例如,标准库的 LinkedList 以这种方式工作:它包含 Option>字段并实现 Send特
我是新手,我正在尝试学习 goroutines 中信号函数的一些基本用法。我在 go 中有一个无限循环。通过这个 for 循环,我通过 channel 将值传递给 goroutine。 我也有一个阈值
如果数据是从另一台计算机(首先)“发送”的,我如何设置我的套接字例程以“发送”(首先)或(切换)“接收”? 谢谢 通用代码: -(void) TcpClient{ char buffer[12
这个问题已经有答案了: Java multiple file transfer over socket (3 个回答) 已关闭 4 年前。 我正在使用 Java Socket 将文件发送到服务器,然后
根据以下示例中的类型,Go编译器似乎将执行两个完全不同的语义操作: chanA <-chanB 如果chanA是类型(chan chan <-字符串),则此操作会将本身类型chanB的类型(chan
我正在尝试在 VBA 中使用 WinSock2 从本地主机 TCP 流发送(以及稍后接收)数据。 目前,我主要尝试从此处复制客户端示例,https://msdn.microsoft.com/en-us
我在我的 Mac OS X Yosemite 控制台中看到了这个: AppleEvents: Send port for process has no send right, port=( port:
我知道Clojure的“代理”是ref,带有“操作”的添加工作队列。 Action 是使用ref的值在第一个位置调用的函数,可以将其传递给其他参数。操作将返回ref的新值。因此,“代理”是一种计算re
我无法将任何对象或数组传递给 IPCRenderer。 通过 ipcs 传递对象或数组时出现错误,我什至尝试通过使用 JSON.stringify 转换为字符串来发送,但它会将其转换为空对象字符串。
我正在使用unix scoket进行数据传输(SOCK_STREAM模式) 我需要发送超过100k个字符的字符串。首先,我发送一个字符串的长度-它是sizeof(int)个字节。 length = s
Clojure API 将这两个函数描述为: (send a f & args) - Dispatch an action to an agent. Returns the agent immedia
def send_Button(): try: myMsg = "ME: " + text.get() msg = text.get() con
Ruby 对象都有一个“发送”方法,但是,我正在尝试使用一个 Java 库 ( netty-tools ),它的一个接口(interface)上有一个“发送”方法。 用法应该是 java_obj.se
Feb 8, 2011 11:56:49 AM com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPC onnection post SEVE
来自 man 2 send: MSG_MORE (since Linux 2.4.4) (…) Since Linux 2.6, this flag is also supported for UDP
我的网页中可以有一个按钮,用于将预填充的消息发送到特定号码吗? 我正在尝试 intent://send/+391234567890#Intent;scheme=smsto;package=com.wh
我是一名优秀的程序员,十分优秀!