通过套接字发送图片(发送功能)在c ++中,但没有收到完整(Windows)!

时间:2013-09-24 13:44:03

标签: c++ windows sockets send recv

我正在从客户端向服务器发送数据,但图片无法完成。

客户代码:

FILE *fr = fopen(tmppicsend, "rb");
char* buffer;
buffer = (char*) malloc(sizeof(char)*size);
fread(buffer, size, 1, fr);
send_len_pic = send( m_socket_pic, buffer, size, 0 );
recv( m_socket_pic, rec_end_check, 32, 0 );
fclose(fr);
free(buffer);

服务器代码:

FILE *fw = fopen(fname, "wb");
char* buffer;
buffer = (char*) malloc(sizeof(char)*size);
int rec_len = recv( current_client, buffer, size, 0 );
buffer[size]='\0';
fwrite(buffer, size, 1, fw);
size -= size;
free(buffer);
fclose(fw);

配置套接字:

WSADATA wsaData_pic;
SOCKET m_socket_pic;
SOCKET m_backup_pic;
sockaddr_in con_pic;

 // Initialize Winsock.
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData_pic );
if ( iResult != NO_ERROR ){
    //printf("Error at WSAStartup()\n");
}
// Create a socket.
m_socket_pic = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

if ( m_socket_pic == INVALID_SOCKET ) {
    //printf( "Error at socket(): %ld\n", WSAGetLastError() );
    //WSACleanup();
}

m_backup_pic = m_socket_pic;

// Connect to a server.
con_pic.sin_family = AF_INET;
con_pic.sin_addr.s_addr = inet_addr( ip );
con_pic.sin_port = htons( 2200 );

if ( connect( m_backup_pic, (SOCKADDR*) &con_pic, sizeof(con_pic) ) == SOCKET_ERROR) {
    //printf( "Failed to connect.\n" );
    //WSACleanup();
}else
{   
    m_socket_pic=m_backup_pic;
}


}

当我比较这些图片时,我看到序列号包中的错误(数据包没有定期接收)。 图片(来自客户端和服务器的图片)大小相同。 我想发送JPEG图片。

请帮助我,坦克。

7 个答案:

答案 0 :(得分:10)

你犯了通常的错误。你不能假设recv()填充缓冲区。您必须循环,直到获得所需的所有数据,并且必须使用recv()返回的计数值。

答案 1 :(得分:2)

您如何知道服务器端要接收的数据大小?您应该在服务器和客户端之间建立某种协议(由您自己定义)。最简单的方法是首先发送uint64_t(8个字节)来保存图片大小,然后发送数据本身。然后在服务器读取前8个字节后 - 它将知道预期的数据量。然后,您只需重复recv()调用,直到获得客户端发送的所有数据。最好在服务器端使用select()等待下一个数据部分可用。顺便说一句,如果您要发送的图片足够大(并且在大多数情况下确实如此),它将通过tcp或udp连接逐个部分发送,而不是通过一个大部分发送。并且它是不可预测的(硬件决定它)它们的大小或它们将被发送多少。所以你绝对应该准备好重复调用recv()来接收客户端发送给服务器的所有数据。

答案 2 :(得分:0)

我认为原因是您要发送的数据大小, 因为当你通过网络发送大数据包时,底层会将这个大数据包分成小数据包,然后通过网络发送这些数据包。

所以当你收到这些数据包时,这些数据包的顺序可能会改变, 这就是为什么你收到相同大小的数据,但图像不正确。

我会给你一个你可以尝试的快速解决方案,

将你的文件分成小数组,假设每个数组都是1024字节,首先发送这些数组的计数,然后开始发送第一个数组(1024字节),然后等待来自另一方的确认,重复直到你发送所有数据。

你可以在没有确认的情况下做到这一点,但在每次发送之间留出一段时间。

答案 3 :(得分:0)

您是否尝试将图像缓冲区转换为base64,将其发送到接收器 - 代码的一部分然后取消基础和malloc?

以上方式是我们的截图程序如何工作(用于远程管理),它就像一个魅力..

答案 4 :(得分:0)

客户端代码

    /*
     * Send size of the file first.
     */

    n = sizeof(filesize);
    r = send(m_socket_pic, &filesize, n);
    if (r != n) {
        printf("error sending %d bytes\n", n);
    }       

    /*
     * Now send the file.
     */

    n = filesize;
    while (n > 0) {
        r = send(m_socket_pic, buffer, n, 0);
        buffer += r;
        n -= r;    
    }       

服务器代码

    /*
     * Recv size of the file first.
     */

    n = sizeof(filesize);
    r = recv(current_client, &filefsize, n);
    if (r != n) {
        printf("error receiving %d bytes\n", n);
    }

    /*
     * Now recv the file.
     */

    n = filesize;
    while (n > 0) {
        r = recv(current_client, buffer, n, 0);
        buffer += r;
        n -= r;
    }

答案 5 :(得分:0)

感谢所有人,

问题是,通过套接字发送大文件。

我有很多方法测试,但没有回答问题。

众所周知,我应该使用循环来发送分割数据。

最佳分割大小为512或1500,问题出在recv()函数中,此函数比send()函数慢。当我在循环块中使用Sleep(1000)时,减少了受损照片的数量。

答案 6 :(得分:0)

我有很多尝试回答。

这个问题的最佳答案是:

将客户端与服务器同步以发送流。

因为recv()函数比send()函数慢,所以客户端发送服务器能够接收的数据量。


客户代码:

char* bufferCMP;
bufferCMP = (char*)malloc(sizeof(char) * size);
p_file = fopen(tmppicsend,"rb");
fread(bufferCMP, 1, size , p_file);
fclose(p_file);


int chunkcount = size / DEFAULT_BUFLEN;
int lastchunksize = size - (chunkcount * DEFAULT_BUFLEN);
int fileoffset=0;

//Sending Actual Chunks
while (chunkcount > 0)
{
    iResult = send( m_socket_pic, bufferCMP + (fileoffset * DEFAULT_BUFLEN) , DEFAULT_BUFLEN , 0 );
    fileoffset++;
    chunkcount--;

    if (iResult != DEFAULT_BUFLEN)
    {
        //printf("Sending Buffer size <> Default buffer length  ::: %d\n",WSAGetLastError());
    }
    else
    {
        //printf("Sending Buffer size = %d \n", iResult);
    }
}

//Sending last Chunk
iResult = send( m_socket_pic, bufferCMP + (fileoffset * DEFAULT_BUFLEN) , lastchunksize , 0 );

服务器代码:

int FileCounter=0;
bool flg=true;
char * fileComplete;
char * filesizeBuffer;

FILE *temp;

int iResult;

int receiveBuffer = 0;
int desiredRecBuffer = size ;
//int desiredRecBuffer = DEFAULT_BUFLEN ; 
fileComplete = (char*) malloc (sizeof(char)* size );
while (desiredRecBuffer > 0)
{
    iResult = recv( current_client, fileComplete + receiveBuffer , desiredRecBuffer , 0 );
    //iResult = recv( ClientSocket, fileComplete + receiveBuffer , fileSize , 0 );

    if (iResult < 1)
    {
        //printf("Reveive Buffer Error  %d \n", WSAGetLastError());
    }
    else
    {
        receiveBuffer += iResult;
        desiredRecBuffer = size - receiveBuffer ;
        //printf("Reveived Data size :  %d \n", iResult);
    }
}

FILE *File = fopen(fname, "wb");
fwrite(fileComplete,1, size , File);
//flg = true;
free(fileComplete);
fclose(File);