简体   繁体   English

C中send()的最大size_t值

[英]max size_t value on send() in C

I'm writing a tcp server in C but I'm facing problems on send. 我正在用C语言编写一个TCP服务器,但是在发送时遇到了问题。 I read local file and send data back to the client, when the file is small I have no problems, but when it becomes bigger I have this strange situation: 我读取本地文件并将数据发送回客户端,当文件较小时,我没有问题,但是当文件较大时,我遇到了这种奇怪的情况:

server tcp: 服务器tcp:

 // create socket, bind, listen accept

// read file
fseek(fptr, 0, SEEK_SET);
// malloc for the sending buffer
ssize_t read = fread(sbuf, 1, file_size, fptr);

while(to_send>0) {
  sent = send(socket, sbuf, buf_size, 0);
  sbuf += sent;
  to_send -= sent;
}

On huge files sent becomes equals to the max value of size_t, I think that I have a buffer overflow. 在发送的巨大文件上,它等于size_t的最大值,我认为我有缓冲区溢出。 How can I prevent this? 我该如何预防? What is the best practice to read from a file and send it back? 从文件读取并将其发送回的最佳实践是什么?

The problem is that you send buf_size bytes every time, even if there aren't that many left. 问题是,即使没有那么多的buf_size ,您每次都发送buf_size字节。

For example, pretend buf_size is 8 and you are sending 10 bytes (So initially, to_send is also 10). 例如,假装buf_size为8,则您要发送10个字节(因此最初, to_send也是10)。 The first send sends 8 bytes, so you need to send 2 more. 第一次send发送8个字节,因此您需要再发送2个字节。 The second time, you also send 8 bytes (Which probably reads out of bounds). 第二次,您还发送8个字节(可能超出范围)。 Then, to_send will be will be -6, which is the same as SIZE_MAX - 5 . 然后, to_send将为-6,与SIZE_MAX - 5相同。

Simple fix is to send to_send if it is smaller: 一个简单的解决方法是发送to_send如果较小):

sent = send(socket, sbuf, to_send < buf_size ? to_send : buf_size, 0);

Also, send returns -1 if it is unsuccessful. 另外,如果send失败,则send返回-1 This is the same as SIZE_MAX when it is assigned to a size_t . 分配给size_t时,这与SIZE_MAX相同。 You would need some error handling to fix this. 您将需要一些错误处理才能解决此问题。

On huge files sent becomes equals to the max value of size_t, I think that I have a buffer overflow. 在发送的巨大文件上,它等于size_t的最大值,我认为我有缓冲区溢出。

Since sent gets its value as the return value of send() , and send() returns ssize_t , which is a signed type unlikely to be wider than size_t , it is virtually certain that what is actually happening is that send() is indicating an error by returning -1. 由于sent的值作为send()的返回值,并且send()返回ssize_t ,这是一个有符号的类型,不可能比size_t宽,因此实际上可以确定,实际发生的事情是send()表示一个通过返回-1表示错误。 In that case, it will also be setting errno to a value indicative of the error. 在这种情况下,还将errno为指示错误的值。 It cannot return the maximum value of size_t on any system I've ever had my hands on. 在我曾经使用过的任何系统上,它都无法返回size_t的最大值。

How can I prevent this? 我该如何预防?

In the first place, before you worry about preventing it, you should be sure to detect it by 首先,在担心阻止它之前,请务必确保通过以下方式对其进行检测

  1. declaring sent as a ssize_t to match the return type of send() , not a size_t , and 声明sent作为ssize_t来匹配send()的返回类型,而不是size_t ,并且
  2. checking the value returned into sent for such error conditions. 检查返回到值sent用于这种错误条件。

Second, if you are really dealing with files longer than can be represented by a ssize_t (much less a size_t ), then it is a poor idea to load the whole thing into memory before sending any of it. 其次,如果您处理文件的时间实际上超过了ssize_t所能表示的ssize_t (远小于size_t ),那么在发送任何内容之前将其全部加载到内存中是一个糟糕的主意。 Instead, load it in (much) smaller blocks, and send the data one such block at a time. 取而代之的是,将其装入(很多)较小的块中,然后一次发送一个这样的块中的数据。 Not only will this tend to have lower perceived latency, but it will also avoid any risk associated with approaching the limits of the data types involved. 这不仅会降低感知延迟,而且还能避免与接近所涉及数据类型的限制相关的任何风险。

Additionally, when you do so, be careful to do it right. 此外,当您这样做时,请小心正确地做。 You have done well to wrap your send() call in a loop to account for short writes, but as @Artyer describes in his answer, you don't quite get that right because you do not reduce the number of bytes you try to send on the second and subsequent calls. 您已经很好地将send()调用包装在了一个循环中,以应对简短的写操作,但是正如@Artyer在他的答案中所描述的那样,您并没有完全正确,因为您没有减少尝试发送的字节数在第二次及以后的通话中。

What is the best practice to read from a file and send it back? 从文件读取并将其发送回的最佳实践是什么?

As above. 如上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM