最近在學網絡通信程式設計,根據書上的練習,我寫了個基于Winsock程式設計的聊天室
但是出現了一些錯誤,m_addr.sin_addr.S_un.S_addr=inet_addr(m_strServer.GetBuffer(0));擷取不到正确的IP位址,造成連接配接錯誤。
對話框裡的建立連接配接按鈕函數
void CExample1Dlg::OnConnect()
{
BYTE f0,f1,f2,f3;
m_ServerIp.GetAddress(f0,f1,f2,f3);
CString add;
add.Format(L"%d.%d.%d.%d",f0,f1,f2,f3);
if(m_client.InitAndConnet(m_hWnd,m_uPort,add)==FALSE)//調用下面CClient類裡的InitAndConnet函數
{
return ;
}
}
BOOL CClient::InitAndConnet(HWND hwnd, UINT port, CString m_strserver)
{
m_hWnd=hwnd;
m_uPort=port;
m_strServer=m_strserver;
if(m_hSocket!=NULL)
{
closesocket(m_hSocket);
m_hSocket=NULL;
}
if(m_hSocket==NULL)
{
m_hSocket=socket(AF_INET,SOCK_STREAM,0);
ASSERT(m_hSocket!=NULL);
ClientInit();
}
//準備伺服器的資訊,指定伺服器的位址
m_addr.sin_family=AF_INET;
m_addr.sin_addr.S_un.S_addr=inet_addr(m_strServer.GetBuffer(0));
m_addr.sin_port=htons(m_uPort);//改變端口的資料格式
int ret=0;
int error=0;
ret=connect(m_hSocket,(LPSOCKADDR)&m_addr,sizeof(m_addr));
以上的内容為将2499848384的ip位址轉換成這種“192.168.0.149”格式的IP位址,友善閱讀。
if(ret==SOCKET_ERROR)
{
if(GetLastError()!=WSAEWOULDBLOCK)
{
AfxMessageBox(L"請确認伺服器确實已經打開并工作在同樣的端口!");
return false;
}
}
return TRUE;
}
最終解決辦法:(下午解決此問題~/(≧▽≦)/~啦啦啦)
1.在cpp檔案裡面加上#include <atlbase.h> ,#pragma comment(lib, "WS2_32.lib")(網上資料說用ws2.lib庫檔案,但是我的VS2008編譯時,老是提示此檔案不存在,改成WS2_32.lib的庫檔案時,編譯成功。)
2.在函數最前面加上USES_CONVERSION;
3.使用T2CA,m_addr.sin_addr.S_un.S_addr = inet_addr(T2CA(m_strServer.GetBuffer(0)));
即:
#include ”atlbase.h“
#pragma comment(lib, "WS2_32.lib")
//。。。。。中間的許多代碼省略。。。。。。。。。。//
USES_CONVERSION;
m_addr.sin_addr.S_un.S_addr = inet_addr(T2CA(m_strServer.GetBuffer(0)));
聊天室程式設計在調試的時候,出現了發送的資訊是亂碼
跟蹤調試時發現下面的這個發送消息send()函數是發送的a.GetBuffer()是多字元型,不能轉換成寬字元。編譯時下面函數報錯:
void CClient::SendString(CString a)
{
if(send(m_hSocket,a.GetBuffer(),a.GetLength(),0)==SOCKET_ERROR)
{
AfxMessageBox(L"Client Send data error ");
}
}
報錯内容為:
>正在編譯...
1>Client.cpp
1>./Client.cpp(91) : error C2664: “send”: 不能将參數 2 從“wchar_t *”轉換為“const char *”
1> 與指向的類型無關;轉換要求 reinterpret_cast、C 樣式轉換或函數樣式轉換
///報錯内容結束///
在網上找了一整天,終于找到了一份可以調試成功的資料如下:
//華麗的分割線/
原文章如下://開始
問題:
在用sendto函數發送資訊時,代碼為:
CString strSend;
GetDlgItemText(IDC_EDIT_SEND, strSend);
sendto(m_socket, strSend.GetBuffer(),strlen(charSend)+1, 0, (SOCKADDR* )&addrTo, len);
但編譯後出現error:
error C2664: “sendto”: 不能将參數 2 從“wchar_t *”轉換為“const char *”
在網上search解決辦法,N久的惱怒後,柳暗花明找到一解決辦法如下:
文章原文:
recvfrom 的第二個參數同樣是char* 的指針,但是可以直接接受WCHAR寬字元,真是生氣,但生氣是解決不了問題的,趕快上網找找答案吧,從MSDN到GOOGLE,經過了一小天的研究真可是又火又高興,火的是很多人都是用自己編寫的函數來解決的,可是如果那樣以為簡單的東西又複雜了.高興的是吃過晚飯又繼續尋找答案,最終在一個國外的網頁中找到了答案,隻用了3,4句就搞定了.
下面貼出來,以防再被這個問題所困擾的人:
//注意,這裡的LPCSTR是不可以替換成CHAR的,否則下邊會出現問題
LPCSTR pszNonUnicode;
CString strUnicode;
USES_CONVERSION;
pszNonUnicode = W2A( strUnicode.LockBuffer( ) );
//這句很關鍵如果沒有此句,那麼上邊的strUnicode字元就不可以在使用了.
strUnicode.UnlockBuffer( );
然後就可以用sendto發送想要發送的内容了.
看完文章,該代碼如下,問題得以解決:
CString strSend;
GetDlgItemText(IDC_EDIT_SEND, strSend);
LPCSTR charSend;
USES_CONVERSION;
charSend = W2A( strSend.LockBuffer( ) );
sendto(m_socket, (LPCSTR)(LPCTSTR)charSend,strlen(charSend)+1, 0, (SOCKADDR* )&addrTo, len);
//文章結束
//華麗的分割線/
然後根據我自己寫的内容,将我的代碼更改如下:
void CClient::SendString(CString a)
{
LPCSTR charSend;
USES_CONVERSION;
charSend = W2A(a.LockBuffer());
a.UnlockBuffer();
if(send(m_hSocket,(LPCSTR)(LPCTSTR)charSend,a.GetLength()+1,0)==SOCKET_ERROR)
{
AfxMessageBox(L"Client Send data error ");
}
}
問題終于解決了,然後将其他的一些同樣的錯誤按照上面的方法更改過來,我的這個基于Winsock的聊天室終于編譯成功~/(≧▽≦)/~啦啦啦。在幾個辦公室的夥伴的共同幫忙測試下,測試也沒有問題,成功!嘻~~~ 除此之外,還學到了很多字元型轉換的知識,以及跟蹤調試的方法。加油↖(^ω^)↗,每天學習一點點,每天進步一點點!堅持就是勝利!