发送的是一幅图像.可能是接收数据次序出现了混乱,图像上半部分清楚,下半部分模糊.请大家指教!另外小弟学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;
}
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;
}
好像有点问题吧??arr[0] = (byte)(nValue & 0x000000FF); // 最低位字节数值
arr[1] = (byte)(nValue & 0x0000FF00); // 右移8位
arr[2] = (byte)(nValue & 0x00FF0000); // 右移16位
arr[3] = 0; // 代表最高位数值为0, 因为图像大小不会很大,所以把这个字节设为0
还有,传输失败后没有进一步处理,例如显示错误信息让自己知道。
另外,发送int不用象你这样转换直接在send函数中写(char*)&nSize就可以了,recv也一样。
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;
}
{
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;
}
程序还是有些问题.看了您的下面这段留言,我估计能改好了."刚看了一下,你没有用recv的返回值来计算接收数据的大小。对于TCP协议,不是你每次发多少对方就每次收多少的,recv的返回值才是真正接收到的大小,你可以用一个变量记录总共要接收的数据量,然后循环recv,缓冲区长度都给这个变量的值,每次接收成功后,该变量减去recv的返回值,直到为0结束循环。"还有就是我觉得"发送完数据不要立即断开连接,由接收方来断开"这句话可能不正确,因为建立了连接就要关闭.