[英]How can I send all data over a socket?
我試圖通過套接字發送大量數據,有時當我調用send(在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()
不會返回總數據大小(即必須多次調用)並且圖像中出現黃線或紫線時,它會接收所有數據,並且我懷疑其中有發送數據時出現問題。
我誤解了問題和解決方案的意圖。 感謝@Remy Lebeau的評論以澄清這一點。 基於此,您可以編寫http://beej.us/guide/bgnet/output/print/bgnet_USLetter.pdf 7.3節中給出的sendall()
函數。
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
}
您需要檢查send()的返回值。 特別是,您不能簡單地假設它是發送的字節數,還可能會出現錯誤。 嘗試以下方法:
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;
}
順便說一句:
BYTE const* data
您不會修改它指向的內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.