通过 NetworkStream 发送消息和文件 [英] Sending messages and files over NetworkStream

查看:23
本文介绍了通过 NetworkStream 发送消息和文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对网络编程很陌生,我有一些关于此代码的问题:

I am quite new to network programming and I have a few questions regarding this code:

    if (client.Connected)
            {
                ChangeLabel("Mit dem Server verbunden...");


                NetworkStream stream = client.GetStream();
                FileStream fs = null;
                try
                {
                    fs = new FileStream("Mapeditor2.exe", FileMode.Create);
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message);
                    Environment.Exit(0);
                }

                byte[] bResponse = new byte[16];
                stream.Read(bResponse, 0, 16);
                string sResponse = System.Text.Encoding.UTF8.GetString(bResponse);
                int NoOfPackets = Convert.ToInt32(sResponse);
                float progress = 0;
                float progressPercent = 100.0f / (float)NoOfPackets;

                byte[] buffer = new byte[128];                    
                int bytesRead;

                for (int i = 0; i < NoOfPackets; i++)
                {
                    bytesRead = stream.Read(buffer, 0, 128);
                    fs.Write(buffer, 0, bytesRead);
                    progress += progressPercent;
                    ChangeProgress((int)progress);
                }
                fs.Close();
                stream.Close();
            }

(Client 是一个 TcpClient,连接到服务器)

(Client is a TcpClient, a connection to a server)

现在我尝试为我的地图编辑器制作更新程序,如您所见.首先我发送一个 16 字节的消息,包含之后将发送的包的数量(Mapeditor.exe 文件!),这是客户端的进度条...

Now I try to make an updater for my mapeditor, as you can see. First I send a 16-byte message containing the number of packages that will be send afterwards (the Mapeditor.exe file!), this is for the progressbar of the client...

是否有任何动态方法可以做到这一点?(不是说读取一个 16 字节的数组"并动态地将文本和文件写入流中,客户端会自动知道他何时必须读取文本以及何时读取文件)

Is there any dynamic way to do this? (not saying "read a 16 byte array" and write dynamically text and files into the stream with the client automatically knowing when he has to read text and when files)

我希望如此,或者还有其他编写更新程序/修补程序的方法吗?游戏开发者如何做到这一点?

I hope so, or is there any other way of writing an updater/patcher? How do game developers do this?

谢谢!

PS:有什么办法可以确保客户收到所有包裹,如果有些包裹丢失,只发送这些包裹并放在一起?

PS: Is there any way to make sure the client receives ALL packages, and if some got lost, only send these and put them together?

推荐答案

如果您使用的是 TCP,协议会负责排序、重传等.

If you are using TCP, the protocol takes care of ordering, retransmitting and so on.

关于动态发送/接收数据,您可以使用前缀协议,在该协议中您首先发送一个数字(比如一个 int - 4 个字节),该数字代表即将到来的消息的长度.之后,您发送消息的其余部分.

Regarding sending/receiving data dynamically, you can use a prefix protocol in which you first send a number (say an int - 4 bytes) that represents the length of the message to come. After that you send the rest of the message.

接收器等待 4 个字节,然后将它们转换为整数并等待该字节数.这个过程一次又一次地重复.

The receiver waits for 4 bytes, then converts them into an integer and waits for that amount of bytes. This process repeats again and again.

在您的情况下,首先读取 16 个字节,将其解析为字符串,然后将字符串解析为 int 是没有意义的.您的发件人可以像这样立即将 int 转换为字节:

In your case, there is no point in reading 16 bytes first, parsing that into a string, and then parsing the string into an int. Your sender can convert the int into bytes right away like this:

// lengthBytes.Length = 4 bytes, which is sizeof(int)
byte[] lengthBytes = BitConverter.GetBytes(anInt);

结束然后通过网络发送.

end then sending it on the wire.

然后,在接收端,在您的代码中,您确实喜欢:

Then, at the receiving end, in your code, you do like:

byte[] msgLengthBytes = new byte[sizeof(int)]; // or hardcode 4 here, I'm a generalization junkie
stream.Read(msgLengthBytes, 0, msgLengthBytes.Length);
int msgLength = BitConverter.GetInt32(msgLengthBytes, 0);

此外,与其假设每次从流中读取时,您读取的字节数都是您期望的字节数,您应该使用以下内容:

Also, instead of that for which assumes that every time you read from the stream you read exactly the amount of bytes you are expecting, you should use something like this:

int transfered = 0;
while (transfered < msgLength)
{
    bytesRead = stream.Read(buffer, 0, buffer.Length);
    fs.Write(buffer, 0, bytesRead);

    transfered += bytesRead;

    progress += (bytesRead / msgLength) * 100;
    ChangeProgress(progress); // You can't use int here anymore, use Math to round or something, for your progress bar
}

此外,在我的代码片段中,如果您在流上连续发送数据,那么您可能会在最后一次接收操作中读取一个数量,例如:transfered + bytesRead > msgLengh.你也必须注意这一点.

Also, in my snippet it is possible that the last receive operation you will read an amount such as: transfered + bytesRead > msgLengh, if you send data continuously on the stream. You must take care of that as well.

无论如何,如果我是你并且因为你需要某种进度通知器,我会使用带有异步 BeginRead() 的流.

Anyhow, if I were you and because you need some sort of a progress notifier, I'd use the stream with the async BeginRead().

我只是给了你一个ideea,你可以随心所欲地调整它.

I just gave you an ideea, you can fine-tune it as you wish.

这篇关于通过 NetworkStream 发送消息和文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆