近来没有太多的时间来详细记录周围的东西,今日就记录一波MFC 用socket来传文件,毕竟没用过mfc的socket,认真搞了一天,收获还行,并整理出了一个Demo。下面就把关键点贴出
客户端:
//----------------------------发送文件的线程------------------------------
UINT Thread_Send(LPVOID lpParam)
{
CClientDlg *dlg=(CClientDlg *)lpParam;
(dlg->GetDlgItem(IDC_BTN_SEND))->EnableWindow(FALSE);
CSocket Clientsock; //definition socket.
if(!AfxSocketInit())
{
AfxMessageBox("afxSocketInit Failed");
}
CString IP="";
dlg->GetDlgItem(IDC_EDIT_IP)->GetWindowText(IP);
CString strport="6070";
dlg->GetDlgItem(IDC_EDIT_PORT)->GetWindowText(strport);
int port=atoi(strport);
//创建
if(!Clientsock.Socket())
{
CString str;
str.Format(_T("Socket创建失败: %d"),GetLastError());
(dlg->GetDlgItem(IDC_BTN_SEND))->EnableWindow(TRUE);
AfxMessageBox(str);
}
//连接
// if(!Clientsock.Connect(_T("127.0.0.1"),8088))
if(!Clientsock.Connect(IP,port))
{
CString str;
str.Format(_T("Socket连接失败: %d"),GetLastError());
(dlg->GetDlgItem(IDC_BTN_SEND))->EnableWindow(TRUE);
AfxMessageBox(str);
}
else
{
WIN32_FIND_DATA FindFileData;
CString strPathName; //定义用来保存发送文件路径的CString对象
dlg->GetDlgItemText(IDC_EDIT_FILENAME,strPathName);
FindClose(FindFirstFile(strPathName,&FindFileData));
Clientsock.Send(&FindFileData,sizeof(WIN32_FIND_DATA));
CFile file;
if(!file.Open(strPathName,CFile::modeRead|CFile::typeBinary))
{
AfxMessageBox(_T("文件不存在"));
(dlg->GetDlgItem(IDC_BTN_SEND))->EnableWindow(TRUE);
return 1;
}
//发送
UINT nSize = 0;
UINT nSend = 0;
char szBuff[2048];
while(nSize<FindFileData.nFileSizeLow)
{
memset(szBuff,0x00,2048);
nSend = file.Read(szBuff,2048);
Clientsock.Send(szBuff,nSend);//发送数据
nSize += nSend;
}
file.Close();
Clientsock.Close();
(dlg->GetDlgItem(IDC_BTN_SEND))->EnableWindow(TRUE);
}
return 0;
}
步骤:一、创建CSocket 对象
二、AfxSocketInit();//在哪个线程就在哪个线程里调用这个
三、调用Socket()方法,来创建socket句柄
四、调用Connect()方法,来连接服务器,参数IP,PORT
五、Connect成功就发送数据呗,
六、WIN32_FIND_DATA这个结构体来保存要发送文件的属性,如文件名,文件大小
七、Clientsock.Send(&FindFileData,sizeof(WIN32_FIND_DATA));先把文件属性发送到服务器端
八、以二进制方式打开文件
九、开一个2kb的缓存
十、读取文件缓存,再发送到服务器,如此循环即将文件发送完毕!
服务器端:
//----------------------------监听文件的线程------------------------------
bool m_exit = false;
unsigned int StartServer(LPVOID lParam)
{
if (!AfxSocketInit())
{
AfxMessageBox("InitFailed");
return 1;
}
m_exit = false;
CServerDlg *aDlg = (CServerDlg *)lParam;
CString strPort;
aDlg->GetDlgItemText(IDC_EDIT_PORT, strPort);
UINT nPort = atoi(strPort);//获取端口号
//socket------------------------------------------------
CSocket aSocket, serverSocket;
if (!aSocket.Socket())
{
char szError[256] = {0};
sprintf(szError, "Create Faild: %d", GetLastError());
AfxMessageBox(szError);
return 1;
}
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
aSocket.SetSockOpt(SO_REUSEADDR, (void *)&bOptVal, bOptLen, SOL_SOCKET);
if (!aSocket.Bind(nPort))
{
char szError[256] = {0};
sprintf(szError, "Bind Faild: %d", GetLastError());
AfxMessageBox(szError);
return 1;
}
if(!aSocket.Listen(10))
{
char szError[256] = {0};
sprintf(szError, "Listen Faild: %d", GetLastError());
AfxMessageBox(szError);
return 1;
}
CString strText;
strText = "Server Start! \r\n";
aDlg->m_list_info.AddString(strText);
while(!m_exit)
{
if(!aSocket.Accept(serverSocket))
{
continue;
}
else
{
WIN32_FIND_DATA FileInfo;
serverSocket.Receive(&FileInfo,sizeof(WIN32_FIND_DATA));
CString strpath("");
CString strname("");
strname.Format("%s",FileInfo.cFileName);
strpath="C://";
CFile file;
if(!file.Open(strpath+strname,CFile::modeCreate|CFile::modeWrite))
{
AfxMessageBox("文件打开失败!已存在");
break;
}
//Receive文件的数据
UINT nSize = 0;
UINT nData = 0;
char szBuff[2048];
while(nSize<FileInfo.nFileSizeLow)
{
memset(szBuff,0x00,2048);
nData=serverSocket.Receive(szBuff,2048);
file.Write(szBuff,nData);
nSize+=nData;
}
serverSocket.Close();
file.Close();
SYSTEMTIME t; //系统时间结构
GetLocalTime(&t);
CString strinfo;
strinfo.Format("文件接收成功..保存在C盘下.\r\n时间:%d年%d月%d日 %2d:%2d:%2d \r\n",t.wYear,t.wMonth,t.wDay,
t.wHour,t.wMinute,t.wSecond);
aDlg->m_list_info.AddString(strinfo);
}
}
aSocket.Close();
serverSocket.Close();
aDlg->m_list_info.AddString("have closed");
return 0;
}
步骤:一、创建CSocket 对象
二、AfxSocketInit();//在哪个线程就在哪个线程里调用这个
三、调用Socket()方法,来创建socket句柄
四、调用SetSockOpt方法,配置socket
五、Bind绑定一个端口
六、Listen监听Socket
七、循环调用Accept来判断有无接入的客户端
八、读取数据,以客户端发送的方式再读取即可!
总体来说各框架的socket基本如出一辙。下面放出的DEMO,基于VC6.0的。
SendAll 与RecvAll
下载链接:http://download.csdn.net/detail/what951006/9885473 //使用的是WINAPI不是CSocket
更多文章:http://blog.csdn.net/what951006?viewmode=list
powered by:小乌龟在大乌龟背上~