㈠ MFC CSocket編程, error C2065: 「IDP_SOCKETS_INIT_FAILED」: 未聲明的標識符。各位大神幫幫忙啊,謝謝了
你在建立MFC工程的時候沒有選用SOCKET選項。。所以他有些資源沒有給你加進去。。。
你在資源文件裡面的Resource.h裡面加一行
#define IDP_SOCKETS_INIT_FAILED 103
應該就可以了(不過我在網上看別人的帖子的時候看到過不是103而是104的我也不知道怎麼回事,103是我自己電腦上自動帶出來的值)
㈡ vc++6.0編的基於MFC的簡單的tcp聊天程序
4.1伺服器端代碼
開啟伺服器功能:
void OnServerOpen() //開啟伺服器功能
{
WSADATA wsaData;
int iErrorCode;
char chInfo[64];
if (WSAStartup(WINSOCK_VERSION, &wsaData)) //調用Windows Sockets DLL
{ MessageBeep(MB_ICONSTOP);
MessageBox("Winsock無法初始化!", AfxGetAppName(), MB_OK|MB_ICONSTOP);
WSACleanup();
return; }
else
WSACleanup();
if (gethostname(chInfo, sizeof(chInfo)))
{ ReportWinsockErr("\n無法獲取主機!\n ");
return; }
CString csWinsockID = "\n==>>伺服器功能開啟在埠:No. ";
csWinsockID += itoa(m_pDoc->m_nServerPort, chInfo, 10);
csWinsockID += "\n";
PrintString(csWinsockID); //在程序視圖顯示提示信息的函數,讀者可自行創建
m_pDoc->m_hServerSocket=socket(PF_INET, SOCK_STREAM, DEFAULT_PROTOCOL);
//創建伺服器端Socket,類型為SOCK_STREAM,面向連接的通信
if (m_pDoc->m_hServerSocket == INVALID_SOCKET)
{ ReportWinsockErr("無法創建伺服器socket!");
return;}
m_pDoc->m_sockServerAddr.sin_family = AF_INET;
m_pDoc->m_sockServerAddr.sin_addr.s_addr = INADDR_ANY;
m_pDoc->m_sockServerAddr.sin_port = htons(m_pDoc->m_nServerPort);
if (bind(m_pDoc->m_hServerSocket, (LPSOCKADDR)&m_pDoc->m_sockServerAddr,
sizeof(m_pDoc->m_sockServerAddr)) == SOCKET_ERROR) //與選定的埠綁定
{ReportWinsockErr("無法綁定伺服器socket!");
return;}
iErrorCode=WSAAsyncSelect(m_pDoc->m_hServerSocket,m_hWnd,
WM_SERVER_ACCEPT, FD_ACCEPT);
//設定伺服器相應的網路事件為FD_ACCEPT,即連接請求,
// 產生相應傳遞給窗口的消息為WM_SERVER_ACCEPT
if (iErrorCode == SOCKET_ERROR)
{ ReportWinsockErr("WSAAsyncSelect設定失敗!");
return;}
if (listen(m_pDoc->m_hServerSocket, QUEUE_SIZE) == SOCKET_ERROR) //開始監聽客戶連接請求
{ReportWinsockErr("伺服器socket監聽失敗!");
m_pParentMenu->EnableMenuItem(ID_SERVER_OPEN, MF_ENABLED);
return;}
m_bServerIsOpen = TRUE; //監視伺服器是否打開的變數
return;
}
響應客戶發送聊天文字到伺服器:ON_MESSAGE(WM_CLIENT_READ, OnClientRead)
LRESULT OnClientRead(WPARAM wParam, LPARAM lParam)
{
int iRead;
int iBufferLength;
int iEnd;
int iRemainSpace;
char chInBuffer[1024];
int i;
for(i=0;(i
//MAXClient是伺服器可響應連接的最大數目
{}
if(i==MAXClient) return 0L;
iBufferLength = iRemainSpace = sizeof(chInBuffer);
iEnd = 0;
iRemainSpace -= iEnd;
iBytesRead = recv(m_aClientSocket[i], (LPSTR)(chInBuffer+iEnd), iSpaceRemaining, NO_FLAGS);
//用可控緩沖接收函數recv()來接收字元
iEnd+=iRead;
if (iBytesRead == SOCKET_ERROR)
ReportWinsockErr("recv出錯!");
chInBuffer[iEnd] = '\0';
if (lstrlen(chInBuffer) != 0)
{PrintString(chInBuffer); //伺服器端文字顯示
OnServerBroadcast(chInBuffer); //自己編寫的函數,向所有連接的客戶廣播這個客戶的聊天文字
}
return(0L);
}
對於客戶斷開連接,會產生一個FD_CLOSE消息,只須相應地用closesocket()關閉相應的Socket即可,這個處理比較簡單。
4.2客戶端代碼
連接到伺服器:
void OnSocketConnect()
{ WSADATA wsaData;
DWORD dwIPAddr;
SOCKADDR_IN sockAddr;
if(WSAStartup(WINSOCK_VERSION,&wsaData)) //調用Windows Sockets DLL
{MessageBox("Winsock無法初始化!",NULL,MB_OK);
return;
}
m_hSocket=socket(PF_INET,SOCK_STREAM,0); //創建面向連接的socket
sockAddr.sin_family=AF_INET; //使用TCP/IP協議
sockAddr.sin_port=m_iPort; //客戶端指定的IP地址
sockAddr.sin_addr.S_un.S_addr=dwIPAddr;
int nConnect=connect(m_hSocket,(LPSOCKADDR)&sockAddr,sizeof(sockAddr)); //請求連接
if(nConnect)
ReportWinsockErr("連接失敗!");
else
MessageBox("連接成功!",NULL,MB_OK);
int iErrorCode=WSAAsyncSelect(m_hSocket,m_hWnd,WM_SOCKET_READ,FD_READ);
//指定響應的事件,為伺服器發送來字元
if(iErrorCode==SOCKET_ERROR)
MessageBox("WSAAsyncSelect設定失敗!");
}
接收伺服器端發送的字元也使用可控緩沖接收函數recv(),客戶端聊天的字元發送使用數據可控緩沖發送函數send(),這兩個過程比較簡單,在此就不加贅述了。
㈢ mfc的TCP連接的雙向通信程序 伺服器端的accept函數怎麼寫
//服務端:
//伺服器接受線程數據
UINT CTcpSrvDlg::ReThreadFunc(LPVOID lParam)
{
CTcpSrvDlg *pDlgSrv = (CTcpSrvDlg*)lParam;
WORD wVersionRequested;//當前網路Socket版本號
WSADATA wsaData;//定義當前網路信息對象
int err;
int iError ;
CString str;
wVersionRequested = MAKEWORD( 1, 1 );//(1.1)版本
//===1、初始化網路設備環境===
err = WSAStartup( wVersionRequested, &wsaData );
//如果WSAStartup返回值為0,則初始化成功
if ( err != 0 )
{
return 1L;
}
//如果網路環境版本不對應,則清空網路設備環境並結束當前線程
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
{
AfxMessageBox("版本不匹配");
//清空網路設備環境
::WSACleanup();
return 1L;
}
//===2、載入套接字===
SOCKET socketSvr = ::socket(AF_INET/*通信區域*/, SOCK_STREAM/*數據流式——TCP*/, 0);
if (INVALID_SOCKET == ::WSAGetLastError())
{
AfxMessageBox("載入套接字失敗");
::WSACleanup();
::closesocket(socketSvr);
return 1L;
}
//===3、套接字綁定
//初始化當前主機地址信息結構體對象
SOCKADDR_IN addSrv;
addSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//允許任何IP的主機與之相連
addSrv.sin_family = AF_INET;//通信網際域
addSrv.sin_port = htons(7000);//0——65355埠,自定義要大一些>1000
iError = ::bind(socketSvr, (SOCKADDR*)&addSrv, sizeof(SOCKADDR_IN));
//校驗是否綁定成功
if (SOCKET_ERROR == iError)
{
AfxMessageBox("套接字綁定失敗");
::WSACleanup();
::closesocket(socketSvr);
return 1L;
}
//===監聽===
iError = ::listen(socketSvr, SOMAXCONN/*等待連接堆內的最大來訪者個數,
如果設置為SOMAXCONN,
則下層的服務提供者負責將套接字設置backlog值為最大的合理的值。*/
);
if (SOCKET_ERROR == iError)
{
AfxMessageBox("監聽失敗");
::WSACleanup();
::closesocket(socketSvr);
return 1L;
}
//===5、接受請求的客戶機的套接字信息===
SOCKET sockClient;
SOCKADDR_IN addrClient;
int iAddrLen = sizeof(SOCKADDR_IN);
while (1)
{
//接受對方的套接字信息
::accept(socketSvr/*伺服器接受*/, (SOCKADDR*)&addrClient, &iAddrLen);
//===6、接受客戶端發過來的數據===
char recvBuf[100];
iError = ::recv(sockClient, recvBuf, 100, 0);
if(SOCKET_ERROR == iError)
{
AfxMessageBox("數據接受失敗");
}
//將接受過來的數據顯示ListBox中
str.Format("%s",recvBuf);
pDlgSrv->m_lbRecv.AddString(str);
}
::closesocket(socketSvr);
::WSACleanup();
return 1L;
}
㈣ 基於mfc的socket編程怎麼進行文件傳輸
1. 採用了多線程的方法,文件傳輸時使用AfxBeginThread()開啟新線程
void CClientsockDlg::OnBnClickedSend()
{
pThreadSend = AfxBeginThread(Thread_Send,this);/
}
文件的發送和接收都開起了新線程
UINTThread_Send(LPVOID lpParam)
{
代碼略…
}
2. 支持從配置文件configuration.ini中獲取伺服器參數
採用GetPrivateProfileString()和GetPrivateProfileInt()分別獲取位於ServerConfiguration.ini文件中的String類型的IP和int類型的port
CString IP;
int port;
GetPrivateProfileString
(L"ServerConfiguration",L"IP",L"沒有讀取到數據!",IP.GetBuffer(10),10,L".\\configuration.ini");
port=GetPrivateProfileInt(L"ServerConfiguration",L"port",0,L".\\configuration.ini");
3. 採用了面向對象的設計方式,功能之間按模塊劃分
MFC本身具有良好的面向對象的特性,本程序嚴格按照MFC框架結構編寫代碼,每個按鈕對應一個功能函數,降低了代碼之間的耦合性,有利於程序的擴展和復用。
void CServersockDlg::OnBnClickedChoose()
void CServersockDlg::OnBnClickedSend()
void CServersockDlg::OnBnClickedRecvdata()
void CServersockDlg::OnBnClickedAbout()
void CServersockDlg::OnBnClickedWriteini()
4. 採用了CSocket類,代碼相對更簡單
CSocket類是MFC框架對socket編程中的winsockAPI的封裝,因此通過這個類管理收發數據更加便利。代碼也跟那個既簡單易懂。
//創建
if(!Clientsock.Socket())
{
CString str;
str.Format(_T("Socket創建失敗:%d"),GetLastError());
AfxMessageBox(str);
}
//連接
if(!Clientsock.Connect(IP,port))
{
CString str;
str.Format(_T("Socket連接失敗:%d"),GetLastError());
AfxMessageBox(str);
}
else
{
AfxMessageBox(_T("Socket連接成功"));
代碼略…
//發送
while(nSize<FindFileData.nFileSizeLow)
{
szBuff = new char[1024];
memset(szBuff,0x00,1024);
nSend =file.Read(szBuff,1024);
Clientsock.Send(szBuff,nSend);//發送數據
nSize += nSend;
}
file.Close();
delete szBuff;
Clientsock.Close();
(dlg->GetDlgItem(IDC_SEND))->EnableWindow(TRUE);
AfxMessageBox(_T("文件發送成功"));
dlg->SetDlgItemTextW(IDC_FILEPATHNAME,_T(""));
}
return 0;
5. 支持數據在伺服器與客戶端之間雙向傳輸
本程序不但可以從客戶端往伺服器端傳文件,而且可以從伺服器端往客戶端傳文件。
但是互傳文件的方式並不是完全相同的。
伺服器端不管是接收文件還是發送文件始終是對綁定的埠進行監聽。
//綁定
if(!Serversock.Bind(port))
{
CString str;
str.Format(_T("Socket綁定失敗: %d"),GetLastError());
AfxMessageBox(str);
}
//監聽
if(!Serversock.Listen(10))
{
CString str;
str.Format(_T("Socket監聽失敗:%d"),GetLastError());
AfxMessageBox(str);
}
客戶端不管是接收文件還是發送文件始終是進行連接。
if(!Clientsock.Connect(IP,port))
{
CString str;
str.Format(_T("Socket連接失ì敗:%d"),GetLastError());
AfxMessageBox(str);
}
else
{
略…
6. 完全圖形化操作界面
二.軟體使用說明
客戶端主界面如圖所示:
單擊「選擇文件」彈出文件對話框,選擇一個要發送的文件,同時保存文件的路徑。
單擊「發送」則會讀取ServerConfiguration.ini文件中的配置信息(IP和port),並根據此信息建立Socket連接,發送文件。注意:伺服器端應該先單擊了「接受客戶端數據」,否則發送失敗。
單擊「接收」也會讀取ServerConfiguration.ini文件中的配置信息(IP和port),並根據此信息建立Socket連接,接收文件。注意:伺服器端應該先選擇了向客戶端發送的文件,並單擊了「發送」,否則接受失敗。
單擊「讀取配置文件」,會從ServerConfiguration.ini文件中讀取配置信息,並以可編輯的文本形式顯示出來,修改完後,單擊「寫入配置文件」,會將修改後的信息保存到配置文件中。
單擊「關於」可以了解到軟體相關信息。
代碼注釋里有更詳細的說明
伺服器端主界面如圖所示
u 單擊「接受客戶端數據」,開始監聽客戶端的鏈接。
u 單擊「選擇文件」彈出文件對話框,選擇一個要發送的文件,同時保存文件的路徑。
u 單擊「發送」則會讀取ServerConfiguration.ini文件中的配置信息(port),並監聽對應埠,准備發送文件。注意:客戶端選擇「接收」以後才能發送成功。
u 單擊「讀取配置文件」,會從ServerConfiguration.ini文件中讀取配置信息,並以可編輯的文本形式顯示出來,修改完後,單擊「寫入配置文件」,會將修改後的信息保存到配置文件中。但是伺服器的IP是不可以修改的,它是在程序開始運行時從伺服器所在機器的網卡上獲取的。
u 單擊「關於」可以了解到軟體相關信息。
u 代碼注釋里有更詳細的說明
代碼下載地址:http://download.csdn.net/detail/leixiaohua1020/6320417
在此附上客戶端使用CSocket發起連接的代碼
[cpp] view plain
//----------------------------發送文件的線程------------------------------
UINT Thread_Send(LPVOID lpParam)
{
CClientsockDlg *dlg=(CClientsockDlg *)lpParam;
(dlg->GetDlgItem(IDC_SEND))->EnableWindow(FALSE);
CSocket Clientsock; //definition socket.
if(!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
}
CString IP;
int port;
GetPrivateProfileString(L"ServerConfiguration",L"IP",L"沒有讀取到數據!",IP.GetBuffer(100),100,L".\\configuration.ini");
port=GetPrivateProfileInt(L"ServerConfiguration",L"port",0,L".\\configuration.ini");
//創建
if(!Clientsock.Socket())
{
CString str;
str.Format(_T("Socket創建失敗: %d"),GetLastError());
AfxMessageBox(str);
}
//連接
// if(!Clientsock.Connect(_T("127.0.0.1"),8088))
if(!Clientsock.Connect(IP,port))
{
CString str;
str.Format(_T("Socket連接失敗: %d"),GetLastError());
AfxMessageBox(str);
}
else
{
AfxMessageBox(_T("Socket連接成功"));
WIN32_FIND_DATA FindFileData;
CString strPathName; //定義用來保存發送文件路徑的CString對象
dlg->GetDlgItemTextW(IDC_FILEPATHNAME,strPathName);
FindClose(FindFirstFile(strPathName,&FindFileData));
Clientsock.Send(&FindFileData,sizeof(WIN32_FIND_DATA));
CFile file;
if(!file.Open(strPathName,CFile::modeRead|CFile::typeBinary))
{
AfxMessageBox(_T("文件不存在"));
return 1;
}
UINT nSize = 0;
UINT nSend = 0;
char *szBuff=NULL;
//發送
while(nSize<FindFileData.nFileSizeLow)
{
szBuff = new char[1024];
memset(szBuff,0x00,1024);
nSend = file.Read(szBuff,1024);
Clientsock.Send(szBuff,nSend);//發送數據
nSize += nSend;
}
file.Close();
delete szBuff;
Clientsock.Close();
(dlg->GetDlgItem(IDC_SEND))->EnableWindow(TRUE);
AfxMessageBox(_T("文件發送成功"));
dlg->SetDlgItemTextW(IDC_FILEPATHNAME,_T(""));
}
return 0;
}
以及伺服器端使用CSocket監聽的代碼:
[cpp] view plain
//----------------------------監聽文件的線程------------------------------
UINT Thread_Func(LPVOID lpParam) //接收文件的線程函數
{
CServersockDlg *dlg = (CServersockDlg *)lpParam; //獲取對話框指針
(dlg->GetDlgItem(IDC_RECVDATA))->EnableWindow(FALSE);
if(!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
}
CString IP;
int port;
GetPrivateProfileString(L"ServerConfiguration",L"IP",L"沒有讀取到數據!",IP.GetBuffer(100),100,L".\\configuration.ini");
port=GetPrivateProfileInt(L"ServerConfiguration",L"port",0,L".\\configuration.ini");
char errBuf[100]={0};// 臨時緩存
SYSTEMTIME t; //系統時間結構
CFile logErrorfile;
if(!logErrorfile.Open(_T("logErrorfile.txt"),CFile::modeCreate|CFile::modeReadWrite))
{
return 1;
}
CSocket Serversock;
CSocket Clientsock;
//創建
if(!Serversock.Socket())
{
CString str;
str.Format(_T("Socket創建失敗: %d"),GetLastError());
AfxMessageBox(str);
}
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
Serversock.SetSockOpt(SO_REUSEADDR,(void *)&bOptVal,bOptLen,SOL_SOCKET);
//綁定
if(!Serversock.Bind(port))
{
CString str;
str.Format(_T("Socket綁定失敗: %d"),GetLastError());
AfxMessageBox(str);
}
//監聽
if(!Serversock.Listen(10))
{
CString str;
str.Format(_T("Socket監聽失敗: %d"),GetLastError());
AfxMessageBox(str);
}
GetLocalTime(&t);
sprintf_s(errBuf,"伺服器已經啟動...正在等待接收文件...\r\n時間:%d年%d月%d日 %2d:%2d:%2d \r\n",t.wYear,t.wMonth,t.wDay,
t.wHour,t.wMinute,t.wSecond);
int len = strlen(errBuf);
logErrorfile.Write(errBuf,len);
AfxMessageBox(_T("啟動成功等待接收文件"));
while(1)
{
//AfxMessageBox(_T("伺服器啟動成功..."));
if(!Serversock.Accept(Clientsock)) //等待接收
{
continue;
}
else
{
WIN32_FIND_DATA FileInfo;
Clientsock.Receive(&FileInfo,sizeof(WIN32_FIND_DATA));
CFile file;
file.Open(FileInfo.cFileName,CFile::modeCreate|CFile::modeWrite);
//AfxMessageBox(FileInfo.cFileName);
int length = sizeof(FileInfo.cFileName);
logErrorfile.Write(FileInfo.cFileName,length);
//Receive文件的數據
UINT nSize = 0;
UINT nData = 0;
char *szBuff=NULL;
while(nSize<FileInfo.nFileSizeLow)
{
szBuff = new char[1024];
memset(szBuff,0x00,1024);
nData=Clientsock.Receive(szBuff,1024);
file.Write(szBuff,nData);
nSize+=nData;
}
delete szBuff;
Serversock.Close();
Clientsock.Close();
file.Close();
(dlg->GetDlgItem(IDC_RECVDATA))->EnableWindow(TRUE);
sprintf_s(errBuf,"文件接收成功...\r\n時間:%d年%d月%d日 %2d:%2d:%2d \r\n",t.wYear,t.wMonth,t.wDay,
t.wHour,t.wMinute,t.wSecond);
int len = strlen(errBuf);
logErrorfile.Write(errBuf,len);
//AfxMessageBox(_T("文件接收成功..."));
break;
}
}
return 0;
}