我的服务器程序接收到的字节不完整。为什么?我正在使用 C# .net 套接字

发布于 2025-01-05 22:57:57 字数 2411 浏览 1 评论 0原文

这种情况并不总是发生。但这种情况比完全接收字节更常见。

这就是我的客户端程序向我的服务器程序发送字节的方式:

public void sendBytes()
{
    FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    TcpClient cli = tcpServer; //tcpServer is a global TcpClient variable I use to connect to the server. 
    NetworkStream ns = cli.GetStream();

    CopyStreamToStream(fs, ns, null);
    ns.Flush();
}

public static void CopyStreamToStream(Stream source, Stream destination, Action<Stream, Stream, Exception> completed)
{
    byte[] buffer = new byte[0x1000];
    int read;

    while ((read = source.Read(buffer, 0, buffer.Length)) > 0) // <- client loop
        destination.Write(buffer, 0, read);
}

这就是我的服务器程序从我的客户端程序接收字节的方式:

FileStream ms = new FileStream(tmpFile, FileMode.Create, FileAccess.Write);
do
{
    int szToRead = s.Available; //s is a socket
    byte[] buffer = new byte[szToRead];

    int szRead = s.Receive(buffer, szToRead, SocketFlags.None);
    if (szRead > 0)
        ms.Write(buffer, 0, szRead);            
}
while(s.Available != 0); //i also tried ms.length < size_of_file_to_be_received_in_bytes

我进入程序并观察了这些值,但我不知道是什么导致缺少接收到的字节。我不知道问题是出在客户端编程还是服务器编程。

我不知道这是否相关,但是当我尝试进入客户端循环(观察 fs.length 的值并检查服务器是否会收到它)时,所有 4 次尝试都从客户端发送文件到服务器成功。但是当我没有观察客户端循环,而只观察服务器应用程序(以查看 ms.length 的值)时,向服务器发送文件的 4 次尝试中只有 1 次成功。在 3 次失败的尝试中,ms.length 小于源文件的字节数(我在文件的属性中检查了它)。

是我根据

附加信息得出的:

基于原始信息代码(来自我基于我的程序的网站),循环有一个不同的条件:

FileStream ms = new FileStream(tmpFile, FileMode.Create, FileAccess.Write);
do
{
    int szToRead = s.Available; //s is a socket
    byte[] buffer = new byte[szToRead];

    int szRead = s.Receive(buffer, szToRead, SocketFlags.None);
    if (szRead > 0)
        ms.Write(buffer, 0, szRead);            
}
while(SocketConnected(s)); // <--- i changed this in my program

private static bool SocketConnected(Socket s)
{
    return !(s.Poll(1000, SelectMode.SelectRead) && (s.Available == 0));
}

我认为 SocketConnected 测试套接字是否仍然连接,因为客户端程序的原始代码是这样的:

CopyStreamToStream(fs, ns, null);
ns.Flush();
ns.Close();

我删除了ns.Close() 从程序中,因为我想保持客户端应用程序与服务器的连接。因此,我希望能够检查是否已读取完来自客户端应用程序的所有字节,而无需从客户端关闭套接字连接。

This doesn't always happen. But it happens more often than receiving the bytes completely.

This is how my client prog sends bytes to my server prog:

public void sendBytes()
{
    FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    TcpClient cli = tcpServer; //tcpServer is a global TcpClient variable I use to connect to the server. 
    NetworkStream ns = cli.GetStream();

    CopyStreamToStream(fs, ns, null);
    ns.Flush();
}

public static void CopyStreamToStream(Stream source, Stream destination, Action<Stream, Stream, Exception> completed)
{
    byte[] buffer = new byte[0x1000];
    int read;

    while ((read = source.Read(buffer, 0, buffer.Length)) > 0) // <- client loop
        destination.Write(buffer, 0, read);
}

This is how my server prog receives bytes from my client prog:

FileStream ms = new FileStream(tmpFile, FileMode.Create, FileAccess.Write);
do
{
    int szToRead = s.Available; //s is a socket
    byte[] buffer = new byte[szToRead];

    int szRead = s.Receive(buffer, szToRead, SocketFlags.None);
    if (szRead > 0)
        ms.Write(buffer, 0, szRead);            
}
while(s.Available != 0); //i also tried ms.length < size_of_file_to_be_received_in_bytes

i stepped into the program and watched the values, and I don't know what causes the lack of bytes received. I don't know if the problem is with the client prog or the server prog.

i don't know if this is relevant, but when i tried stepping into the client loop (to watch the value of fs.length and check if it will be received in the server), all 4 attempts to send a file from the client to the server succeeded. but when i did not watch the client loop, and only watch the server app (to see the value of ms.length), only 1 of 4 attempts to send a file to the server succeeded. on the 3 failed attempts, ms.length is less than the bytes of the source file (i checked it in the file's property).

This is where I based this from

ADDITIONAL INFORMATION:

On the original code (from the website I based my program), the loop has a different condition:

FileStream ms = new FileStream(tmpFile, FileMode.Create, FileAccess.Write);
do
{
    int szToRead = s.Available; //s is a socket
    byte[] buffer = new byte[szToRead];

    int szRead = s.Receive(buffer, szToRead, SocketFlags.None);
    if (szRead > 0)
        ms.Write(buffer, 0, szRead);            
}
while(SocketConnected(s)); // <--- i changed this in my program

private static bool SocketConnected(Socket s)
{
    return !(s.Poll(1000, SelectMode.SelectRead) && (s.Available == 0));
}

I think the SocketConnected tests if the socket is still connected because the original code for the client program was this:

CopyStreamToStream(fs, ns, null);
ns.Flush();
ns.Close();

i removed the ns.Close() from the program because I want to maintain the connection of the client application to the server. So I want to be able to check if I'm done reading all the bytes coming from the client app without closing the socket connection from the client side.

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

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

发布评论

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

评论(1

堇色安年 2025-01-12 22:57:57

如果可用为零,这并不意味着您已完成读取字节。这意味着当前,在这一纳秒内,没有字节排队。服务器如何知道将来会有多少字节到来?

在良好的近似下,每次使用Available都是一个错误!

删除可用的所有用法。相反,始终尝试读取完整的缓冲区。如果你得到 0,这意味着套接字已关闭,你就完成了。

编辑:这是一些规范的读取代码:

var buffer = new byte[8192];
while(true) {
 var readCount = stream.Read(buffer, 0, buffer.Length);
 if (readCount == 0) break;
 outputStream.Write(buffer, 0, readCount);
}

If Available is zero this does not mean that you have finished reading bytes. It means that currently, in this nanosecond, there are no bytes queued. How could the server know how many bytes will be coming in the future?

In good approximation, every singe use of Available is an error!

Delete all usages of Available. Instead, always try to read a full buffer. If you get 0 this means the socket has been closed and you are done.

Edit: Here is some canonical read code:

var buffer = new byte[8192];
while(true) {
 var readCount = stream.Read(buffer, 0, buffer.Length);
 if (readCount == 0) break;
 outputStream.Write(buffer, 0, readCount);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文