2013-04-25 37 views
0

我想通过套接字发送大量数据,有时当我调用发送(在Windows上)时,它不会发送我所请求的所有数据,如预期的那样。所以,我写了一个应该解决了我的问题的小函数 - 但是它导致数据未被正确发送并导致图像被破坏的问题。我正在创建一个简单的聊天室,您可以将图像(截图)发送给对方。如何通过套接字发送所有数据?

为什么我的功能不工作?

我该如何让它工作?

void _internal_SendFile_alignment_512(SOCKET sock, BYTE *data, DWORD datasize) 
{  
    Sock::Packet packet; 
    packet.DataSize = datasize; 
    packet.PacketType = PACKET_FILETRANSFER_INITIATE; 
    DWORD until = datasize/512; 

    send(sock, (const char*)&packet, sizeof(packet), 0); 

    unsigned int pos = 0; 

    while(pos != datasize) 
    { 
     pos += send(sock, (char *)(data + pos), datasize - pos, 0); 
    } 

} 

我的接收端是:

public override void OnReceiveData(TcpLib.ConnectionState state) 
{ 
    if (state.fileTransfer == true && state.waitingFor > 0) 
    { 
     byte[] buffer = new byte[state.AvailableData]; 
     int readBytes = state.Read(buffer, 0, state.AvailableData); 
     state.waitingFor -= readBytes; 
     state.bw.Write(buffer); 
     state.bw.Flush(); 

     if (state.waitingFor == 0) 
     { 
      state.bw.Close(); 
      state.hFile.Close(); 
      state.fileTransfer = false; 
      IPEndPoint ip = state.RemoteEndPoint as IPEndPoint; 
      Program.MainForm.log("Ended file transfer with " + ip); 
     } 
    } 
    else if(state.AvailableData > 7) 
    {   
     byte[] buffer = new byte[8]; 
     int readBytes = state.Read(buffer, 0, 8); 
     if (readBytes == 8) 
     { 
      Packet packet = ByteArrayToStructure<Packet>(buffer); 
      if (packet.PacketType == PACKET_FILETRANSFER_INITIATE) 
      { 
       IPEndPoint ip = state.RemoteEndPoint as IPEndPoint; 
       String filename = getUniqueFileName("" + ip.Address); 
       if (filename == null) 
       { 
        Program.MainForm.log("Error getting filename for " + ip); 

        state.EndConnection(); 
        return; 
       } 

       byte[] data = new byte[state.AvailableData]; 
       readBytes = state.Read(data, 0, state.AvailableData); 

       state.waitingFor = packet.DataSize - readBytes; 
       state.hFile = new FileStream(filename, FileMode.Append); 
       state.bw = new BinaryWriter(state.hFile); 
       state.bw.Write(data); 
       state.bw.Flush(); 
       state.fileTransfer = true; 
       Program.MainForm.log("Initiated file transfer with " + ip); 
      } 
     } 
    } 
} 

它接收的所有数据,当我调试我的代码,看到send()不返回的总数据量(即它被称为多一次),图像中出现黄线或紫线 - 我怀疑发送数据有问题。

+0

的[发送图像在C++套接字(Linux)的(HTTP可能重复解决的事情:/ /stackoverflow.com/q/3125080/427192),尽管这不是Linux – 2013-04-25 19:14:32

回答

1

我误解了问题和解决方案的意图。感谢@Remy Lebeau发表评论以澄清这一点。基于这一点,你可以写一个sendall()功能在7.3节给出的http://beej.us/guide/bgnet/output/print/bgnet_USLetter.pdf

int sendall(int s, char *buf, int *len) 
{ 
    int total = 0; // how many bytes we've sent 
    int bytesleft = *len; // how many we have left to send 
    int n = 0; 
    while(total < *len) { 
     n = send(s, buf+total, bytesleft, 0); 
     if (n == -1) { 
      /* print/log error details */ 
      break; 
     } 
     total += n; 
     bytesleft -= n; 
    } 
    *len = total; // return number actually sent here 
    return n==-1?-1:0; // return -1 on failure, 0 on success 
} 
+0

由于OP的代码没有发送固定大小的数据块,datasize-pos是传递给send()的正确大小。它允许send()尽可能多的接收数据,然后返回实际接受的字节数。 – 2013-04-25 19:31:57

0

您需要检查发送的返回值()。特别是,你不能简单地认为它是发送的字节数,也有错误的情况。试试这个:

while(datasize != 0) 
{ 
    n = send(...); 
    if(n == SOCKET_ERROR) 
     throw exception("send() failed with errorcode #" + to_string(WSAGetLastEror())); 
    // adjust pointer and remaining number of bytes 
    datasize -= n; 
    data += n; 
} 

BTW:

  • 作出这样的BYTE const* data,你不会修改它指向。
  • 你的代码的其余部分似乎太复杂了,尤其是你不对准幻数像512
相关问题