我是一名刚开始学MFC的大学生,试着编了一个用socket传输文件的程序。
思路是把文件一次性读入缓冲区,然后用TCP发送,接收方一次性把文件接收入缓冲区,然后再写成文件。
我试着用这个程序传送了一些小的文本文件,一切正常,也传了一些MP3,正常。
但是在传送一些100多M的RMVB视频文件时,接收到的文件却无法打开
请问各位高手这是怎么回事呢?谢谢了。该开始学,分不多,请见谅。程序代码如下:服务器端:void CFileTransDlg::OnSend()
{
// TODO: Add your control notification handler code here
CFileDialog fd(true);
CString filename;
char fn[40];
SOCKET listenSocket;
SOCKET socketSend;
unsigned int listen_port;
CFile file;
int FileLength;
char *data; struct sockaddr_in localaddr;
struct sockaddr_in clientaddr; listen_port=5050; int AddrSize; AddrSize = sizeof(clientaddr); if(IDOK == fd.DoModal())
{ filename = fd.GetFileName();
if(!file.Open(filename.GetBuffer(0),CFile::modeRead|CFile::typeBinary))
{
AfxMessageBox("打开文件错误,取消发送!");
return;
}
strcpy(fn,filename.GetBuffer(0)); }
else return; listenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
socketSend = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(listen_port);
if (bind(listenSocket, (struct sockaddr *)&localaddr,
sizeof(localaddr)) == SOCKET_ERROR)
{
AfxMessageBox("绑定socket失败 : %d\n", WSAGetLastError());
return ;
}
listen(listenSocket,20);
socketSend = accept(listenSocket,(struct sockaddr *)&clientaddr,&AddrSize); FileLength = file.GetLength();
char acBuf[50] = { 0 };
sprintf(acBuf, "%d", FileLength); send(socketSend,acBuf,50,0);
send(socketSend,fn,40,0); data = new char[FileLength]; file.ReadHuge(data,FileLength); send(socketSend,data,FileLength,0);
file.Close();
delete data;
closesocket(socketSend); WSACleanup();
}客户端:void CFileTransClientDlg::OnReceive()
{
// TODO: Add your control notification handler code here
SOCKET socketReceive;
CFile file;
long FileLength = 0;
char tem[50];
char *data;
char fn[40];
struct sockaddr_in server;
unsigned int server_port=5050; server.sin_family = AF_INET;
server.sin_port = htons(server_port);
server.sin_addr.s_addr = inet_addr("222.25.136.114");
InitWinsock(); socketReceive = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
connect(socketReceive,(struct sockaddr *)&server,sizeof(server)); recv(socketReceive,tem,50,0); FileLength = chartoint(tem); recv(socketReceive,fn,40,0); data = new char[FileLength]; recv(socketReceive,data,FileLength,0); file.Open(fn,CFile::modeCreate |CFile::modeWrite|CFile::typeBinary); file.WriteHuge(data,FileLength); file.Close();
delete data;
closesocket(socketReceive); AfxMessageBox("接收文件成功!"); WSACleanup();
}
思路是把文件一次性读入缓冲区,然后用TCP发送,接收方一次性把文件接收入缓冲区,然后再写成文件。
我试着用这个程序传送了一些小的文本文件,一切正常,也传了一些MP3,正常。
但是在传送一些100多M的RMVB视频文件时,接收到的文件却无法打开
请问各位高手这是怎么回事呢?谢谢了。该开始学,分不多,请见谅。程序代码如下:服务器端:void CFileTransDlg::OnSend()
{
// TODO: Add your control notification handler code here
CFileDialog fd(true);
CString filename;
char fn[40];
SOCKET listenSocket;
SOCKET socketSend;
unsigned int listen_port;
CFile file;
int FileLength;
char *data; struct sockaddr_in localaddr;
struct sockaddr_in clientaddr; listen_port=5050; int AddrSize; AddrSize = sizeof(clientaddr); if(IDOK == fd.DoModal())
{ filename = fd.GetFileName();
if(!file.Open(filename.GetBuffer(0),CFile::modeRead|CFile::typeBinary))
{
AfxMessageBox("打开文件错误,取消发送!");
return;
}
strcpy(fn,filename.GetBuffer(0)); }
else return; listenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
socketSend = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(listen_port);
if (bind(listenSocket, (struct sockaddr *)&localaddr,
sizeof(localaddr)) == SOCKET_ERROR)
{
AfxMessageBox("绑定socket失败 : %d\n", WSAGetLastError());
return ;
}
listen(listenSocket,20);
socketSend = accept(listenSocket,(struct sockaddr *)&clientaddr,&AddrSize); FileLength = file.GetLength();
char acBuf[50] = { 0 };
sprintf(acBuf, "%d", FileLength); send(socketSend,acBuf,50,0);
send(socketSend,fn,40,0); data = new char[FileLength]; file.ReadHuge(data,FileLength); send(socketSend,data,FileLength,0);
file.Close();
delete data;
closesocket(socketSend); WSACleanup();
}客户端:void CFileTransClientDlg::OnReceive()
{
// TODO: Add your control notification handler code here
SOCKET socketReceive;
CFile file;
long FileLength = 0;
char tem[50];
char *data;
char fn[40];
struct sockaddr_in server;
unsigned int server_port=5050; server.sin_family = AF_INET;
server.sin_port = htons(server_port);
server.sin_addr.s_addr = inet_addr("222.25.136.114");
InitWinsock(); socketReceive = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
connect(socketReceive,(struct sockaddr *)&server,sizeof(server)); recv(socketReceive,tem,50,0); FileLength = chartoint(tem); recv(socketReceive,fn,40,0); data = new char[FileLength]; recv(socketReceive,data,FileLength,0); file.Open(fn,CFile::modeCreate |CFile::modeWrite|CFile::typeBinary); file.WriteHuge(data,FileLength); file.Close();
delete data;
closesocket(socketReceive); AfxMessageBox("接收文件成功!"); WSACleanup();
}
我应该怎样才能加上验证呢?不麻烦你帮忙写代码,只要讲一下思路就可以了。另外能告诉我该去看书上的那一部分相关知识吗?
我想把这个问题弄清楚。再次谢谢了!
1,每个send函数的返回值
2,每个recv函数的返回值
3,如果send函数返回的值没有发送完所有数据,需要再次发送剩余数据。
检查一下啊
调用一次send,send返回512,说明这次send只发送成功了512字节
应该再次调用send,发送下面的512字节,
去看msdn
谢谢了!
但是现在还不明白一个地方。
Send函数有三个参数,我要怎样确定它从那个字节开始发呢?
还是我把没发完的数据再放入另一个缓冲区,然后调用Send发送呢?
另外recv函数,要怎么样才能控制它接收了数据后加入刚才的缓冲区后面呢?
还是我要重新开辟一片缓冲区,然后接受完后,再连接起来?
while(nLeft > 0){
//can write
int nSent = ::send(s,
pszBuffer + (nLength - nLeft),nLeft,0);
if(SOCKET_ERROR == nSent){
//error
break;
}
else{
nLeft -= nSent;
}
}