在用socket传输文件中发现传输一直出错,客户端显示信息发送成功,然后客户端出现端口关闭提示.在服务器端一直没有接收到任何数据,提示在一个非套接字上尝试了一个操作.
大体程序如下:
客户端 :
1.BOOL CClientDlg::InitSocket(f0,f1,f2,f3,m_port)
{
int ret;
sockaddr_in m_addr;
CString add;
add.Format ("%d.%d.%d.%d",f0,f1,f2,f3); if(m_sockClient !=NULL)
{
closesocket(m_sockClient);
m_sockClient =NULL;
} if(m_sockClient ==NULL)
{
m_sockClient = socket(AF_INET,SOCK_STREAM,0);
if(m_sockClient == INVALID_SOCKET)
{
AfxMessageBox(GetError(WSAGetLastError()));
//closesocket(m_sockClient);
return FALSE;
}
else
{
//AfxMessageBox("端口创建成功");
} if( WSAAsyncSelect (m_sockClient,this->m_hWnd ,CLI_MSG,FD_CONNECT|FD_CLOSE)>0)
{
AfxMessageBox(GetError(WSAGetLastError()));
//closesocket(m_sockClient);
return FALSE;
}
else
{
//AfxMessageBox("选择成功");
} m_addr.sin_family =  AF_INET;
m_addr.sin_addr.S_un .S_addr =inet_addr(add.GetBuffer (0));
m_addr.sin_port= htons(m_port); ret =connect(m_sockClient,(LPSOCKADDR)&m_addr,sizeof(m_addr));
if(ret ==SOCKET_ERROR)
{
AfxMessageBox(GetError(WSAGetLastError()));
//closesocket(m_sockClient);
return FALSE;
}
else
{
//AfxMessageBox("连接成功");
}
} return TRUE;
}2.LRESULT CClientDlg::OnClientMsg(WPARAM wParam,LPARAM lParam)
{
switch(lParam)
{
case FD_CONNECT:
int err;
if((err=GetLastError())!=0)
{
AfxMessageBox(GetError(err));
}
else
{
SendFile(m_fileName);
}
return 0; /*case FD_CLOSE:
if(m_sockClient!=NULL)
closesocket(m_sockClient);
return 0;*/ default:
//AfxMessageBox("网络故障");
/*if(m_sockClient!=NULL)
closesocket(m_sockClient);*/ return 0;
}
}
3.void CClientDlg::SendFile(CString fileName)
{
FILEINFO fileInfo;
int num=0,temp=0,end=0; CFile f(fileName,CFile::shareDenyWrite|CFile::typeBinary);
fileInfo.fileLength =f.GetLength ();
fileInfo.fileName =fileName;
char *iBuff = new char[sizeof(fileInfo.fileLength )];
memcpy(iBuff,&fileInfo.fileLength ,sizeof(fileInfo.fileLength)); ////////////////////////发送文件长度信息
if(send(m_sockClient,iBuff,sizeof(fileInfo.fileLength),0)==SOCKET_ERROR )
{
AfxMessageBox(GetError(WSAGetLastError()));
return ;
}
else
{
//AfxMessageBox("发送文件长度信息成功");
} ////////////////////////发送文件名信息
if(send(m_sockClient,fileInfo.fileName.GetBuffer (0),sizeof(fileInfo.fileName),0)==SOCKET_ERROR )
{
AfxMessageBox(GetError(WSAGetLastError()));
return ;
}
else
{
//AfxMessageBox("发送文件名信息成功");
} ///////////////////////发送文件
f.Seek (0,CFile::begin);
char m_buf[1024]={0};
for(;;)
{
num = f.Read (m_buf,1024 );
if(num==0) 
break; end=send(m_sockClient,m_buf, num,0);
if(end==SOCKET_ERROR)
{
AfxMessageBox(GetError(WSAGetLastError()));
break;
}
else
{
//AfxMessageBox("发送成功");
}
temp+=end;
} if(temp!=fileInfo.fileLength)
{
//AfxMessageBox("文件发送不成功");
return;
}
else
{
AfxMessageBox("文件发送成功");
} //closesocket(m_sockClient);
}服务器端:
1.void CServerDlg::OnSetServer() 
{
// TODO: Add your control notification handler code here
if(m_sockServer!=NULL)
{
//closesocket(m_sockServer);
m_sockServer=NULL;
} if(m_sockServer==NULL)
{
m_sockServer=socket(AF_INET,SOCK_STREAM,0);
if(m_sockServer == INVALID_SOCKET)
{
//closesocket(m_sockServer);
AfxMessageBox("端口创建失败");
return ;
}
else
{
//AfxMessageBox("端口创建成功");
} if( WSAAsyncSelect (m_sockServer,this->m_hWnd ,SER_MSG,FD_CONNECT|FD_READ|FD_ACCEPT|FD_CLOSE)>0)
{
//closesocket(m_sockServer);
AfxMessageBox(GetError(WSAGetLastError()));
return ;
}
else
{
//AfxMessageBox("选择成功");
}
m_addr.sin_family =AF_INET;
m_addr.sin_addr .S_un .S_addr =INADDR_ANY;
m_addr.sin_port =htons(m_port); int ret=0; ret = bind(m_sockServer,(LPSOCKADDR)&m_addr,sizeof(m_addr));
if(ret == SOCKET_ERROR)
{
//closesocket(m_sockServer);
AfxMessageBox(GetError(WSAGetLastError()));
return;
}
else
{
//AfxMessageBox("绑定成功");
} ret =listen(m_sockServer,1);
if(ret == SOCKET_ERROR)
{
AfxMessageBox(GetError(WSAGetLastError()));
return;
}
else
{
//AfxMessageBox("建立成功");
}
}

}2.LRESULT CServerDlg::OnServerMsg(WPARAM wParam, LPARAM lParam)
{
SOCKET conSock;
char buf[1024]={0};
int len=0;
FILEINFO fileInfo;
CFile tempFile;
bool fileOpen=false;
int total=0; switch(lParam)
{
case FD_CONNECT:
AfxMessageBox("FD_CONNECT");
return 0; case FD_ACCEPT:
AfxMessageBox("FD_ACCEPT");
conSock = accept(m_sockServer,NULL,NULL);
if(conSock==INVALID_SOCKET )
{
//closesocket(conSock);
AfxMessageBox(GetError(WSAGetLastError()));
AfxMessageBox("与客户端连接失败");
}
else
{
//AfxMessageBox("FD_ACCEPT");
} return 0; case FD_READ:
AfxMessageBox("FD_READ");
len =recv(conSock,buf,1024,0);
if(len>=0)
{
switch(type)
{
case 0:
fileInfo.fileLength =atoi(buf);
type =1;
break; case 1:
fileInfo.fileName.Format ("%s",buf);
type =2;
break; case 2:
if(len!=0)
{
if(fileOpen ==false)
{
if(tempFile.Open (fileInfo.fileName ,CFile::modeWrite|CFile::modeCreate) ==false)
{
AfxMessageBox("文件打开失败");
tempFile.Close ();
}
fileOpen= true;
}
tempFile.Write (buf,len);
total +=len;
}
else
{
type = 0;
tempFile.Close ();
//closesocket(conSock);
}
if(total ==fileInfo.fileLength )
{
HANDLE hBitmap = LoadImage(0,fileInfo.fileName,IMAGE_BITMAP,0,0,LR_DEFAULTSIZE | LR_LOADFROMFILE);
m_bmp.SetBitmap((HBITMAP)hBitmap);
} break;
}
}
else
{
AfxMessageBox(GetError(WSAGetLastError()));
} return 0; case FD_CLOSE:
AfxMessageBox("FD_CLOSE");
if(conSock!=NULL)
{
//closesocket(conSock);
}
return 0; default:
//AfxMessageBox("网络故障");
if(conSock!=NULL)
{
//closesocket(conSock);
}
return 0;
}
}

解决方案 »

  1.   

    一般来说这个问题的原因是服务器端提前退出,所以在客户端上检测到socket断开,在开发的注意在服务器端也进行检测是否真的读写文件完毕然后在退出程序.
      

  2.   

    不好意思,刚才没有详细看代码,你的问题恰好相反,虽然客户端显示文件已经发送完毕,但是此时服务器端还没有接受完毕,很有可能都还没有开始接受,发送成功的显示并不代表着服务器端已经成功的接受了,数据在进入系统缓冲区的时候就会显示socket已经发送成功了,此时客户端的退出当然会导致socket的端口关闭和连接的断开.
      解决的办法很简单,当客户端发送完毕后再需要等待一个服务器端接受完毕的信号再退出客户端程序就可以了.
      

  3.   

    楼主你的设置的SOCKET conSock;是局部变量,当收到 FD_READ消息后,他又被重新初始化了,是一个无效的socket句柄,所以你收不到数据了你应该在服务程序中保存一下客户端socket的句柄要改的太多,看看别人的例子吧!
      

  4.   

    对,
    SOCKET conSock;是局部变量,有问题。