Winsock聊天室编程笔记

来源:互联网 发布:阿里云qq 编辑:程序博客网 时间:2024/05/22 15:46

最近在学网络通信编程,根据书上的练习,我写了个基于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));

/*在XP系统环境下,使用VS2008编译环境的 Unicode 字符集,Debug编译时,此句错误,报错为:error C2664: “inet_addr”: 不能将参数 1 从“wchar_t *”转换为“const char *” ,我将这句的类型做强制转换,m_addr.sin_addr.S_un.S_addr=inet_addr((const char *)m_strServer.GetBuffer(0));

但是转换之后,我设置的IP地址为“192.168.0.149”,而我跟踪单步调试,发现编译时获取的IP地址地址为“0.0.0.1”,是错误的。

 但是直接这样赋值,编译又是对的m_addr.sin_addr.S_un.S_addr=inet_addr(“192.168.0.149“);  此问题求解中?中午未解决!!!

*/
 m_addr.sin_port=htons(m_uPort);//改变端口的数据格式

 int ret=0;
 int error=0;
 ret=connect(m_hSocket,(LPSOCKADDR)&m_addr,sizeof(m_addr));
 /*char * ipaddr=NULL;
      char addr[20];
      in_addr inaddr;
      inaddr. s_addr=2499848384;//计算机是认不出“192.168.0.149”的IP地址方式的,要经过转换变成2499848384
      ipaddr= inet_ntoa(inaddr);
     strcpy(addr,ipaddr);*/以上/*~~*/的内容为将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的聊天室终于编译成功~/(≧▽≦)/~啦啦啦。在几个办公室的伙伴的共同帮忙测试下,测试也没有问题,成功!嘻~~~ 除此之外,还学到了很多字符型转换的知识,以及跟踪调试的方法。加油↖(^ω^)↗,每天学习一点点,每天进步一点点!坚持就是胜利!

 

 

原创粉丝点击