发送的是一幅图像.可能是接收数据次序出现了混乱,图像上半部分清楚,下半部分模糊.请大家指教!另外小弟学c,c++不久,以前没写过多少程序,欢迎csdn上的高手指教,拍砖!^.^注:发送端和接收端是在同一台机器上,接收部分是接收程序启动的一个线程(不知道这会不会对接收次序产生影响).代码如下:发送端
bool SendFile(const char *pData, int nSize)
{
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);
connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
    
char arr[4];
ConverterInt(nSize, arr);
send(sockClient, arr, 4, 0); // 发送"数据大小"信息 const int nPackageSize = 4096; // nLen代表每次数据的大小 --- 4k
int nTime = nSize / nPackageSize; // 循环发送数据的次数
for(int i = 0; i < nTime; i++)
{
int nResult = send(sockClient, pData + i * nPackageSize, nPackageSize, 0); 
if (nResult == SOCKET_ERROR)
{
break; // 如果发送失败,跳出循环
}
} int nLeave = nSize % nPackageSize;
if( nLeave != 0)
{
send(sockClient, pData + nTime * nPackageSize, nLeave, 0); // 发送剩余数据
} closesocket(sockClient); return true;
}/**********************************************
*  把Int类型转化成4个长度的字符数组
*  Int占用位数为32位时才有效,函数有些缺陷^.^
**********************************************/
static void ConverterInt(int nValue, char arr[])
{
    arr[0] = (byte)(nValue);       // 最低位字节数值
    arr[1] = (byte)(nValue >> 8);  // 右移8位
    arr[2] = (byte)(nValue >> 16); // 右移16位
    arr[3] = 0; // 代表最高位数值为0, 因为图像大小不会很大,所以把这个字节设为0
}// 接收端程序
DWORD WINAPI FunListenProc(LPVOID lpParameter)
{
SOCKET sockSrv=socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000); int nRet = bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
if(nRet == SOCKET_ERROR)
{
closesocket(sockSrv);
return -1;
} int nResult = listen(sockSrv, 1); // 设置监听数为1,只允许一个客户程序连接到服务器
if(nResult == SOCKET_ERROR)
{
closesocket(sockSrv);
return -1;
} SOCKADDR_IN addrClient;
int len=sizeof(SOCKADDR); while (true)
{
SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);

const int nRecv = 4;
char arr[nRecv];
int nCount = recv(sockConn, arr, nRecv, 0);
if(nCount == nRecv)
{
int nSize = (byte)arr[0] + ((byte)arr[1]) * 256 + ((byte)arr[2]) * 256 * 256; 

if(nSize > 0)
{
char *pFile = new char[nSize];
const int nPackageSize = 4096; // nLen代表每次数据的大小 --- 4k
int nTime = nSize / nPackageSize; // 循环接收数据的次数

for(int i = 0; i < nTime; i++)
{
int nRecvSize = recv(sockConn, pFile + nPackageSize * i, nPackageSize, 0);
if(nRecvSize == SOCKET_ERROR)
{
break; // 接收数据出错,跳出循环
}
} int nLeave = nSize % nPackageSize;
if( nLeave != 0)
{
recv(sockConn, pFile + nTime * nPackageSize, nLeave, 0); // 接收剩余数据
} CFile file;
file.Open("Img.jpg",  CFile::modeCreate | CFile::modeWrite);
            file.Write(pFile, nSize); // 写入原文件类型
file.Close();

delete[] pFile; 
pFile = NULL;
}
}
closesocket(sockConn);
}

return 0;
}

解决方案 »

  1.   

    static void ConverterInt(int nValue, char arr[]) 
    好像有点问题吧??arr[0] = (byte)(nValue & 0x000000FF);       // 最低位字节数值 
    arr[1] = (byte)(nValue & 0x0000FF00);  // 右移8位 
    arr[2] = (byte)(nValue & 0x00FF0000); // 右移16位 
    arr[3] = 0; // 代表最高位数值为0, 因为图像大小不会很大,所以把这个字节设为0 
      

  2.   

    发送完数据不要立即断开连接,由接收方来断开。
    还有,传输失败后没有进一步处理,例如显示错误信息让自己知道。
    另外,发送int不用象你这样转换直接在send函数中写(char*)&nSize就可以了,recv也一样。
      

  3.   

    感谢CrownLiu和cnzdgs.奇怪了,把每次发送和接收都改成1k大小就可以,(第一次运行不正常,后面全部都正常,还是有些不稳定).
    bool SendFile(const char *pData, int nSize)
    {
            SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
            SOCKADDR_IN addrSrv;
            addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
            addrSrv.sin_family = AF_INET;
            addrSrv.sin_port = htons(6000);
            connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
        
            send(sockClient, (char*)&nSize, 4, 0); // 发送"数据大小"信息          const int nPackageSize = 1024; // nLen代表每次数据的大小 --- 1k
            int nTime = nSize / nPackageSize; // 循环发送数据的次数
              for(int i = 0; i < nTime; i++)
            {
            int nResult = send(sockClient, pData + i * nPackageSize, nPackageSize, 0); 
            if (nResult == SOCKET_ERROR)
    {
            break; // 如果发送失败,跳出循环
              }
            }        int nLeave = nSize % nPackageSize;
            if( nLeave != 0)
            {
              send(sockClient, pData + nTime * nPackageSize, nLeave, 0); // 发送剩余数据
              }        closesocket(sockClient);        return false;
    }
      

  4.   

    这是接收端程序,也是设成1k大小.DWORD WINAPI FunListenProc(LPVOID lpParameter)
    {
    SOCKET sockSrv=socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
    addrSrv.sin_family=AF_INET;
    addrSrv.sin_port=htons(6000); int nRet = bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
    if(nRet == SOCKET_ERROR)
    {
    closesocket(sockSrv);
    return -1;
    } int nResult = listen(sockSrv, 1); // 设置监听数为1,只允许一个客户程序连接到服务器
    if(nResult == SOCKET_ERROR)
    {
    closesocket(sockSrv);
    return -1;
    } SOCKADDR_IN addrClient;
    int len=sizeof(SOCKADDR); while (true)
    {
    SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);

    int nSize = 0;
    recv(sockConn, (char*)&nSize, 4, 0); if(nSize > 0)
    {
    char *pFile = new char[nSize];
    const int nPackageSize = 1024; // nLen代表每次数据的大小 --- 1k
    int nTime = nSize / nPackageSize; // 循环接收数据的次数

    for(int i = 0; i < nTime; i++)
    {
    int nRecvSize = recv(sockConn, pFile + nPackageSize * i, nPackageSize, 0);
    if(nRecvSize == SOCKET_ERROR)
    {
    break; // 接收数据出错,跳出循环
    }
    } int nLeave = nSize % nPackageSize;
    if( nLeave != 0)
    {
    recv(sockConn, pFile + nTime * nPackageSize, nLeave, 0); // 接收剩余数据
    } CFile file;
    file.Open("Screen.jpg",  CFile::modeCreate | CFile::modeWrite);
            file.Write(pFile, nSize); // 写入原文件类型
    file.Close();

    delete[] pFile; 
    pFile = NULL;
    } closesocket(sockConn);
    }

    return 0;
    }
      

  5.   

    刚看了一下,你没有用recv的返回值来计算接收数据的大小。对于TCP协议,不是你每次发多少对方就每次收多少的,recv的返回值才是真正接收到的大小,你可以用一个变量记录总共要接收的数据量,然后循环recv,缓冲区长度都给这个变量的值,每次接收成功后,该变量减去recv的返回值,直到为0结束循环。
      

  6.   

    谢谢回复,刚刚看了一下可以运行就结贴了.
    程序还是有些问题.看了您的下面这段留言,我估计能改好了."刚看了一下,你没有用recv的返回值来计算接收数据的大小。对于TCP协议,不是你每次发多少对方就每次收多少的,recv的返回值才是真正接收到的大小,你可以用一个变量记录总共要接收的数据量,然后循环recv,缓冲区长度都给这个变量的值,每次接收成功后,该变量减去recv的返回值,直到为0结束循环。"还有就是我觉得"发送完数据不要立即断开连接,由接收方来断开"这句话可能不正确,因为建立了连接就要关闭.
      

  7.   

    我说的是不要立即断开,等到接收方断开后发送方再关闭socket,我是担心数据没有发送成功连接就被断开了,不过现在看起来主要是接收的问题。
      

  8.   

    我说的是不要立即断开,等到接收方断开后发送方再关闭socket.发送端程序和接收端程序不是同一个程序,请问如何实现呢?"刚看了一下,你没有用recv的返回值来计算接收数据的大小。对于TCP协议,不是你每次发多少对方就每次收多少的,recv的返回值才是真正接收到的大小,你可以用一个变量记录总共要接收的数据量,然后循环recv,缓冲区长度都给这个变量的值,每次接收成功后,该变量减去recv的返回值,直到为0结束循环。"再想了想这段话,又有点感觉了,我觉得send的时候也不是发多少就能直接发送成功的.返回值才是真正发送的数据大小.通过循环发送数据,可以累加返回值,直到发完就断开连接,这样理解可以吧.