2013-04-25 67 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
相關問題