MFC下CSocket程式設計詳解
該示例程式碼在VS2003下聯調透過。
[@more@]MFC下CSocket程式設計詳解轉自:http://blog.csdn.net/yejiansnake/archive/2008/03/13/2175778.aspx
MFC下CSocket程式設計詳解:
1. 常用的函式和注意事項(詳細的函式介面說明請檢視MSDN):
CSocket::Create 初始化(一般寫伺服器程式都不要用為好,用下面的 CSocket::Socket 初始化)
CSocket::Socket初始化
CSocket::SetSockOpt 設定socket選項
CSocket::Bind 繫結地址埠
CSocket::Connect 連線
CSocket::Listen 監聽
CSocket::Accept 接收外部連線的socket
CSocket::Send 傳送內容
CSocket::Receive 接收內容
CSocket::Close 關閉(不等於delete)
1) 在使用MFC編寫socket程式時,必須要包含
2) AfxSocketInit() 這個函式,在使用CSocket前一定要先呼叫該函式,否則使用CSocket會出錯;並且該函式還有一個重要的使用方式,
就是在某個執行緒下使用 CSocket 前一定要呼叫,就算主執行緒呼叫了該函式,在子執行緒下使用 CSocket 也要先呼叫該函式,要不會出錯。
3) 還要注意的是, Create 方法已經包含了 Bind 方法,如果是以 Create 方法初始化的前提下不能再呼叫 Bind ,要不一定出錯。
2. 以下是使用例子程式碼,透過例子來學習如何使用 CSocket 進行程式設計, 並且附件上有完整的例子程式碼。例子的可以在我的釋出資源中找到:MFC下CSocket程式設計例子
1) 客戶端主要程式碼:
AfxSocketInit();
//建立 CSocket 物件
CSocket aSocket;
CString strIP;
CString strPort;
CString strText;
this->GetDlgItem(IDC_EDIT_IP)->GetWindowText(strIP);
this->GetDlgItem(IDC_EDIT_PORT)->GetWindowText(strPort);
this->GetDlgItem(IDC_EDIT_TEXT)->GetWindowText(strText);
//初始化 CSocket 物件, 因為客戶端不需要繫結任何埠和地址, 所以用預設引數即可
if(!aSocket.Create())
...{
char szMsg[1024] = ...{0};
sprintf(szMsg, "create faild: %d", aSocket.GetLastError());
AfxMessageBox(szMsg);
return;
}
//轉換需要連線的埠內容型別
int nPort = atoi(strPort);
//連線指定的地址和埠
if(aSocket.Connect(strIP, nPort))
...{
char szRecValue[1024] = ...{0};
//傳送內容給伺服器
aSocket.Send(strText, strText.GetLength());
//接收伺服器傳送回來的內容(該方法會阻塞, 在此等待有內容接收到才繼續向下執行)
aSocket.Receive((void *)szRecValue, 1024);
AfxMessageBox(szRecValue);
}
else
...{
char szMsg[1024] = ...{0};
sprintf(szMsg, "create faild: %d", aSocket.GetLastError());
AfxMessageBox(szMsg);
}
//關閉
aSocket.Close();
2)伺服器端程式碼:
...{
if (!AfxSocketInit())
...{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
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;
//最好不要使用aSocket.Create建立,因為容易會出現10048錯誤 if (!aSocket.Socket())
...{
char szError[256] = ...{0};
sprintf(szError, "Create Faild: %d", GetLastError());
AfxMessageBox(szError);
return 1;
}
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
//設定Socket的選項, 解決10048錯誤必須的步驟
aSocket.SetSockOpt(SO_REUSEADDR, (void *)&bOptVal, bOptLen, SOL_SOCKET);
if(!aSocket.Listen(10))
...{
char szError[256] = ...{0};
sprintf(szError, "Listen Faild: %d", GetLastError());
AfxMessageBox(szError);
return 1;
}
CString strText;
aDlg->GetDlgItemText(IDC_EDIT_LOG, strText);
strText += "Server Start! ";
aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);
while(!m_exit)
...{
//接收外部連線 if(!aSocket.Accept(serverSocket))
...{
continue;
}
else
...{
char szRecvMsg[256] = ...{0};
char szOutMsg[256] = ...{0};
sprintf(szOutMsg, "Receive Msg: %s ", szRecvMsg);
aDlg->GetDlgItemText(IDC_EDIT_LOG, strText);
strText += szOutMsg;
aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);
serverSocket.Send("Have Receive The Msg", 50);
}
}
aSocket.Close();
serverSocket.Close();
aDlg->GetDlgItemText(IDC_EDIT_LOG, strText);
strText += "Have Close!";
aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);
return 0;
}
//繫結埠 if (!aSocket.Bind(nPort))
...{
char szError[256] = ...{0};
sprintf(szError, "Bind Faild: %d", GetLastError());
AfxMessageBox(szError);
return 1;
}
3) SDK 下的伺服器端程式碼
unsigned int StartServer(LPVOID lParam)
...{
//初始化Winsock, AfxSocketInit() 也是封裝了這些語句, 不過 AfxSocketInit() 所做的事比這裡多些
WSADATA wsaData;
//Winsock 的版本, 建議用1.1 ,相容性好
WORD wVersionRequested = MAKEWORD(1, 1);
int nResult = WSAStartup(wVersionRequested, &wsaData);
if (nResult != 0)
...{
return 1;
}
//-----------------------------------------------------
m_exit = false;
CServerDlg *aDlg = (CServerDlg *)lParam;
CString strPort;
aDlg->GetDlgItemText(IDC_EDIT_PORT, strPort);
UINT nPort = atoi(strPort);
//socket------------------------------------------------
//介面物件
SOCKET aSocket, serverSocket;
//定址相關結構
sockaddr_in serverSockaddr;
memset(&serverSockaddr, 0, sizeof(serverSockaddr));
aSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (aSocket == INVALID_SOCKET)
...{
char szError[256] = ...{0};
sprintf(szError, "Create Faild: %d", GetLastError());
AfxMessageBox(szError);
return 1;
}
//注意,該處非常重要,取值的正確與否決定關閉scoket後埠是否能正常釋放
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
//設定 socket 選項, SOL_SOCKET 和 SO_REUSEADDR 一起使用, 並且後面的引數如上,
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/143526/viewspace-1045771/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MFC下CSocket程式設計詳解(轉)程式設計
- MFC--網路程式設計之CAsyncSocket詳解程式設計
- MFC程式設計(五)C程式程式設計
- MFC程式設計(四)C程式程式設計
- MFC程式設計(二)C程式程式設計
- MFC程式設計(一)C程式程式設計
- MFC程式設計(六)C程式程式設計
- MFC程式設計(三)C程式程式設計
- MFC詳解
- MFC——SkinMagic使用詳解
- PHP Socket 程式設計詳解PHP程式設計
- VC++ MFC程式設計版本資訊控制C++C程式程式設計
- CSocket設定超時(轉)
- 泛型程式設計詳解(一)泛型程式設計
- Flutter非同步程式設計詳解Flutter非同步程式設計
- 【網路程式設計】socket詳解程式設計
- Java併發程式設計(06):Lock機制下API用法詳解Java程式設計API
- Linux系統下的Oracle資料庫程式設計詳解LinuxOracle資料庫程式設計
- 併發程式設計——IO模型詳解程式設計模型
- 網路程式設計TCP/IP詳解程式設計TCP
- java網路程式設計(TCP詳解)Java程式設計TCP
- 併發程式設計 — CAS 原理詳解程式設計
- Java 網路程式設計 —— Socket 詳解Java程式設計
- 萬字詳解 | Java 流式程式設計Java程式設計
- RequireJS 模組化程式設計詳解UIJS程式設計
- python超程式設計詳解(3)Python程式設計
- python超程式設計詳解(4)Python程式設計
- python超程式設計詳解(2)Python程式設計
- PHP Socket 程式設計過程詳解PHP程式設計
- No MFC 程式設計01 - 最精簡的 win32 程式 (轉)程式設計Win32
- 新手不能忽視的MFC程式設計之CStringC程式程式設計
- MFC---ActiveX控制元件程式設計基礎控制元件程式設計
- MFC 訊息對映機制詳解
- 併發程式設計——詳解 AQS CLH 鎖程式設計AQS
- Java 併發程式設計(一) → LockSupport 詳解Java程式設計
- python Gui程式設計工具詳解:beewarePythonGUI程式設計
- python函數語言程式設計詳解Python函數程式設計
- java併發程式設計 | 執行緒詳解Java程式設計執行緒