Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何通过套接字发送所有数据?_C++_Sockets_Winsock - Fatal编程技术网

C++ 如何通过套接字发送所有数据?

C++ 如何通过套接字发送所有数据?,c++,sockets,winsock,C++,Sockets,Winsock,我试图通过套接字发送大量数据,有时我调用send(在Windows上)时,它不会像预期的那样发送我请求的所有数据。因此,我编写了一个小函数,它本应该解决我的问题,但它会导致数据发送不正确的问题,并导致图像损坏。我正在制作一个简单的聊天室,在这里你们可以互相发送图片(截图) 为什么我的功能不起作用 我怎样才能让它工作 void _internal_SendFile_alignment_512(SOCKET sock, BYTE *data, DWORD datasize) {

我试图通过套接字发送大量数据,有时我调用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);
            }
        }
    }
}
public override void OnReceiveData(TcpLib.ConnectionState状态)
{
if(state.fileTransfer==true&&state.waitingFor>0)
{
字节[]缓冲区=新字节[state.AvailableData];
int readBytes=state.Read(缓冲区,0,state.AvailableData);
state.waitingFor-=读取字节;
state.bw.Write(缓冲区);
state.bw.Flush();
if(state.waitingFor==0)
{
state.bw.Close();
state.hFile.Close();
state.fileTransfer=false;
IPEndPoint ip=state.RemoteEndPoint作为IPEndPoint;
Program.MainForm.log(“以“+ip”结束文件传输);
}
}
否则如果(state.AvailableData>7)
{          
字节[]缓冲区=新字节[8];
int readBytes=state.Read(缓冲区,0,8);
if(readBytes==8)
{
数据包=字节数组结构(缓冲区);
if(packet.PacketType==数据包\u文件传输\u启动)
{
IPEndPoint ip=state.RemoteEndPoint作为IPEndPoint;
字符串文件名=getUniqueFileName(“+ip.Address”);
如果(文件名==null)
{
Program.MainForm.log(“获取“+ip”的文件名时出错);
state.EndConnection();
返回;
}
字节[]数据=新字节[state.AvailableData];
readBytes=state.Read(数据,0,state.AvailableData);
state.waitingFor=packet.DataSize-readBytes;
state.hFile=新文件流(文件名,FileMode.Append);
state.bw=新的二进制编写器(state.hFile);
state.bw.Write(数据);
state.bw.Flush();
state.fileTransfer=true;
Program.MainForm.log(“使用“+ip”启动文件传输);
}
}
}
}

当我调试代码并看到
send()
未返回总数据大小(即必须多次调用)时,它接收所有数据,并且图像中出现黄线或紫线-我怀疑发送数据有问题。

我误解了问题和解决方案的意图。感谢@Remy Lebeau对此的评论。基于此,您可以编写一个
sendall()
函数,如的第7.3节所示

int sendall(int s,char*buf,int*len)
{
int total=0;//我们发送了多少字节
int bytesleet=*len;//我们还有多少要发送
int n=0;
而(总计<*len){
n=发送(s,buf+总计,字节左,0);
如果(n==-1){
/*打印/记录错误详细信息*/
打破
}
总+=n;
字节左-=n;
}
*len=total;//实际发送到此处的返回编号
return n==-1?-1:0;//失败时返回-1,成功时返回0
}

您需要检查send()的returnvalue。特别是,您不能简单地假设它是发送的字节数,也有发生错误的情况。请尝试以下方法:

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;
}
顺便说一句:

  • 如果设置为
    字节常量*data
    ,则不会修改它指向的内容
  • 代码的其余部分似乎太复杂了,特别是你不能通过对齐像512这样的幻数来解决问题

的可能重复,即使这不是Linux
数据大小-pos
是传递到
send()
的正确大小,因为OP的代码不发送固定大小的块。它允许
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;
}