繁体   English   中英

通过TCP套接字发送大量数据

[英]sending a large amount of data throught TCP socket

这是我在这个论坛上发布的第一个问题,我是c#世界的初学者,所以这对我来说很有意思,但我面临着通过套接字发送大量数据的一些问题,所以这是更多细节关于我的问题:

我正在通过TCP套接字发送5 Mo的二进制映像,在接收部分我保存结果(收到的数据)并且只获得1.5 Mo ==>数据已丢失(我比较了原始文件和生成的文件它向我展示了错过的部分)这是我使用的代码:

private void senduimage_Click(object sender, EventArgs e)
{
    if (!user.clientSocket_NewSocket.Connected)
    {
        Socket clientSocket_NewSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        user.clientSocket_NewSocket = clientSocket_NewSocket;
        System.IAsyncResult _NewSocket = user.clientSocket_NewSocket.BeginConnect(ip_address, NewSocket.Transceiver_TCP_Port, null, null);
        bool successNewSocket = _NewSocket.AsyncWaitHandle.WaitOne(2000, true);
     }
     byte[] outStream = System.Text.Encoding.ASCII.GetBytes(Uimage_Data);
     user.clientSocket_NewSocket.Send(outStream);
 }

在他们说要将数据分成块的论坛中,这是一个解决方案,如果是这样我怎么能这样做,我已经尝试但它没有用!

有很多不同的解决方案但是分块通常是一个很好的解决方案,你可以盲目地做这个,你继续填充你的临时缓冲区,然后把它放到一些状态缓冲区,直到你遇到一些任意的令牌或缓冲区没有完全填满,或者你可以遵守每个tcp 消息的某种合同(消息是要接收的整体数据)。

如果你要考虑做某种合同,那么做一些事情就像消息的前N个字节是描述符,你可以根据需要做大或小,但你的临时缓冲区只能在前面读取这个大小从溪流。

典型的标题可能是这样的:

public struct StreamHeader // 5 bytes
{
   public byte MessageType {get;set;} // 1 byte
   public int MessageSize {get;set;}  // 4 bytes
}

所以你会读到它,如果它足够小,可以将完整的消息大小分配给临时缓冲区并全部读取,或者如果你认为它太大,将它分成几部分并继续读取,直到你收到的总字节数与MessageSize相匹配标题结构的一部分。

可能你还没有在C#中阅读有关套接字使用的文档。 http://msdn.microsoft.com/en-us/library/ms145160.aspx

内部缓冲区无法存储您提供的所有数据以发送方法。 解决问题的可能方法就像您所说的将数据划分为块。

int totalBytesToSend = outstream.length;     int bytesSend = 0;
while(bytesSend < totalBytesToSend )
    bytesSend+= user.clientSocket_NewSocket.Send(outStream, bytesSend, totalBytesToSend - bytesSend,...);

我怀疑你的一个问题是你没有打电话给EndConnect 从MSDN文档:

必须通过调用EndConnect方法来完成异步BeginConnect操作。

还有,等待: -

bool successNewSocket = _NewSocket.AsyncWaitHandle.WaitOne(2000,true);

可能总是假的,因为没有任何东西将事件设置为信号状态。 通常,您可以为BeginConnect函数指定一个回调函数,并在回调中指定您调用EndConnect并将事件的状态设置为发信号。 请参阅此MSDN页面上的示例代码。

UPDATE

我想我看到了另一个问题: -

byte[] outStream = System.Text.Encoding.ASCII.GetBytes(Uimage_Data);

我不知道什么类型的Uimage_Data,但我真的不认为你想将它转换为ASCII。 数据中的零可以表示数据字节的结尾(或者可能是26或其他ASCII码)。 关键是,编码过程可能正在改变数据。

你能提供Uimage_Data对象的类型吗?

最有可能的问题是,在将所有数据传输到服务器之前,您正在关闭客户端套接字,因此它将被丢弃。

默认情况下,关闭套接字时,将丢弃所有未传输的数据(位于操作系统缓冲区中)。 有几个解决方案:

[1]设置SO_LINGER(参见http://developerweb.net/viewtopic.php?id=2982)[2 ]让服务器向客户端发送确认,并且在收到之前不要关闭客户端套接字它。 [3]在关闭套接字之前等到客户端输出缓冲区为空(使用getsocketopt SO_SND_BUF进行测试 - 我不确定c#上的语法)。

你真的应该测试Send()的返回值。 虽然理论上它应该阻塞直到它发送所有数据,但我想要实际验证,并且如果存在不匹配,至少会打印错误消息。

暂无
暂无

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

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