LINUX 中套接字的部分写入

发布于 2024-11-06 09:10:04 字数 890 浏览 0 评论 0原文

我们的应用程序中有服务器-客户端通信。套接字用于通信。 我们使用 AF_INET 套接字和 SOCK_STREAM(TCP/IP)。 这些套接字也处于非阻塞模式 (O_NONBLOCK)。 应用程序是在 UNIX 上用 C++ 编写的。

在我们的系统中,服务器将写入套接字,客户端将从它读取。我们编写了代码来处理部分写入。如果发生部分数据,我们将再尝试 30 次来写入整个数据。

我们的服务器尝试向套接字写入 2464 字节。在某些情况下,它无法写入整个数据。因此服务器将尝试再写入 30 次以传输整个数据。大多数情况下,整个数据将在 30 次尝试内写入。 但有时即使经过 30 次重试,服务器也无法写入全部数据。这里会抛出EAGAIN错误。当客户端尝试读取部分写入的数据时,会出现问题。

考虑服务器尝试写入 2464 字节。但重复30次尝试后只能写入1080字节。服务器此时将发出 EAGAIN。客户端尝试读取 2464 字节。读取命令将返回 2464,因此读取本身正常。但是我们收到的数据是损坏的(仅部分写入的数据)。所以客户端崩溃了。

任何人都可以提出以下建议,

1)是否可以仅删除服务器本身部分写入的数据。因此客户端不会收到损坏的不完整数据? (我们不能使用服务器的 read() 函数来删除它。考虑服务器成功地将 n 条消息写入套接字。客户端处于繁忙状态,无法读取它们。然后服务器尝试写入第 n+1 条消息,并且发生部分写入。如果我们使用来自服务器的读取命令,则整个 n 条成功消息都会被删除,我们只需要删除部分写入(第 n+1 条)消息)

2)有什么方法可以在客户端识别这一点。我们读过部分写成的 信息?。

请注意,我们仅在 LINUX(REDHAT 5.4) 中面临部分写入问题。系统在 Solaris 中工作正常(在 Solaris 中,要么整个数据将被写入,要么在 30 次写入尝试中不会写入任何数据)。

提前致谢。

We have a server-client communication in our application. Sockets are used for the communication.
We are using AF_INET sockets with SOCK_STREAM(TCP/IP).
Also these sockets are in Non Blocking mode (O_NONBLOCK).
Application is written in C++ on UNIX.

In our system the Server will write to a socket and Client will read from it. We had written code to handle partial writes. If a partial happens, we will try 30 more times to write the entire data.

Our Server try to write 2464 bytes to the socket. In some cases it could not write entire data. So server will try writing 30 more times to transfer entire data. Most of the times the entire data will be written within 30 tries.
But some times the even after 30 reties sever wil not be able to write the entire data. Here it will throw EAGAIN error. Problem happens in the Client Side when it tries to read this partially written data.

Consider the server tried to write 2464 bytes. But after the repeated 30 attempts it could write only 1080 bytes. Server will raise a EAGAIN at this point. Client try to read 2464 bytes. The read command will return 2464 and hence the read itself is ok. But the data we received is a corrupted one (Partially written data only). So client crashes.

Can any one please advise on following,

1) Is it possible to remove only the partially written data by the server itself. Thus the client will not recieve corrupted incomplete data?. (We cannot use a read() function from server to remove this. Consider server successfully written n messages to the socket. Client is in busy state and not able to read them. Then the server try to write the n+1 th message and Partial write occured. If we use read command from the server, the entire n successfull messages alo get removed. We need to remove the Partially witten (n+1 th) message only)

2) Is there any way to identify in client side that we had read a partially written message?.

Please note that we are facing the partial write issue in LINUX(REDHAT 5.4) only. System is working fine in Solaris (In solaris either eh entire data will be written OR NO data witll be written with in 30 tries of write).

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谢绝鈎搭 2024-11-13 09:10:04

你的代码中有一些严重错误。

  • 您应该根据需要多次调用 write 来传输您想要的所有数据,我认为没有理由在 30 次后停止

  • 如果您使用非阻塞套接字,您可能应该使用 select() (或 poll(),或者任何类似的内容)以便在您可以写更多内容时收到通知data

  • 接收端有问题 - 如果你发送的数据少于 2464,你应该无法从客户端套接字读取该数量。您是否检查 read() 返回的值(即读取的字节数)?同样,在客户端,您应该使用 select() 等,并根据需要多次调用 read 来接收完整消息。

There's something terribly wrong in your code.

  • you should call write as many times as necessary to transfer all the data you want, I see no reason to stop after 30 times

  • if you're using non-blocking sockets, you should probably use select() (or poll(), or anything similar) to get notified when you can write more data

  • there's something wrong with the receiving end - if you've sent less than 2464, you shouldn't be able to read that amount from the client socket. Do you check the value returned from read() (i.e. number of bytes read)? Again, on the client side you should use select() etc. and call read as many times as needed to receive full message.

黯淡〆 2024-11-13 09:10:04

您所看到的是非阻塞套接字的正常行为。当缓冲区(本地和远程)变满时,您会得到部分写入。

在 30 次产生 EAGAIN/EWOULDBLOCK 的尝试后,您不应该放弃,而应该继续尝试。您应该使用 select()/poll() 或类似的方法来在可以恢复写入时收到通知,或者您应该只使用阻塞调用。您在 Solaris 与 RHEL 上看到不同的结果只是(不)运气。

  1. 不,在这种情况下您必须关闭连接,并让客户端处理部分数据。

  2. 不,除非您关闭 TCP 连接。 (*)

如果您总是发送 2464 字节的消息,那么可能没问题 - 但请记住 TCP 是一个流,它不处理“消息”

(*) 技术上有很多方法,但需要大量的方法努力。例如,您可以自己在 TCP 之上实现 HDLC 之类的帧,其中消息被分隔通过特殊的位模式。用户数据必须进行转义(位填充)以不包含该特殊位模式

What you're seing is normal behavior for a non-blocking socket. When the buffers(both local and remote) become full, you get partial writes.

You should should not give up after 30 tries that yields EAGAIN/EWOULDBLOCK, but keep trying. You should use select()/poll() or similar to get notified when you can resume writing, or you should just use blocking calls. That you see different results on Solaris vs RHEL is just (un)luck.

  1. No, you'd have to close the connection in such a case, and have the client deal with the partial data.

  2. No, not unless you close the TCP connection. (*)

If you always send messages of 2464 bytes, you're probably ok - but keep in mind that TCP is a stream, it does not deal with "messages"

(*) Technically there's many ways, but requires substantial effort. e.g. you could implement HDLC like frames on top of TCP yourself, where messages are delimited by a special bit pattern. The user data would have to be escaped (bit-stuffing) to not contain that special bit pattern

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文