天天看點

Winsock聊天室程式設計筆記

最近在學網絡通信程式設計,根據書上的練習,我寫了個基于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的聊天室終于編譯成功~/(≧▽≦)/~啦啦啦。在幾個辦公室的夥伴的共同幫忙測試下,測試也沒有問題,成功!嘻~~~ 除此之外,還學到了很多字元型轉換的知識,以及跟蹤調試的方法。加油↖(^ω^)↗,每天學習一點點,每天進步一點點!堅持就是勝利!