1 recvfrom sendto的解释

if(-1 != sendto(sockMy, buf, sizeof(buf), 0, (SOCKADDR*)&addrFar, sizeof(SOCKADDR)))

参数依次为:  发送端socket   发送端缓冲区  发送端缓冲区大小  0   接收端地址  sizeof(SOCKADDR)

返回值 :为整型,如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR。


 recvfrom(SockMy, BUF, BUF_SZ, 0, (SOCKADDR*)&AddrFar, &len);

参数意义 依次为   接收端socket  接收端缓冲区 接收端缓冲区大小  0  用来保存数据来源地址  len=sizeof(SOCKADDR)

返回值 :如果正确接收返回接收到的字节数,失败返回-1.


注意 初学者使用sendto的时候容易把接收端的xxx..sin_addr.S_un.S_addr 设置为INADDR_ANY 这是错误的   因为INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。 一般来说,在各个系统中均定义成为0值。 只能在发送端才可以使用INADDR_ANY(服务端客户端都可能是发送端)  ,否则的话就无法判断我们要发送的地址是哪里。

另外我们常用inet_ntoa(addrTo.sin_addr) 这个函数来判断是否正确的地址 它是与inet_addr相反

2  线程相关

因为线程函数必须是 全局的 或者static的   如果定义为全局的 则我们无法让函数属于某个类 这时候我们只能将类的指针传递给此函数 如下

//创建接受消息线程
	HANDLE hThread=CreateThread(NULL,0,RecvProc,this,0,NULL);



创建了一个线程     将this指针传递过去  

DWORD WINAPI RecvProc(LPVOID lpParameter)
{
	CChat *This = (CChat *)lpParameter; 
        
	return 0;
}



如上 我们将可以通过This使用类的成员。   

通常都是定义为static的   


3  全局变量定义的一种方法 

假设工程名为520Chat  则在MFC自动生成的类CMy520ChatApp的头文件中添加 我们需要的全局变量 如int UserId  在构造函数中初始化

当使用全局变量时 添加 CMy520ChatApp *app = (CMy520ChatApp *)AfxGetApp();  这句话   

通过 app->UserId 便可以使用全局变量



4  CString转换成char*

CString theString; 
 
       .....................;
 
       char* lpsz =(LPTSTR)(LPCTSTR)theString;


5  添加自定义消息

工作线程中不能使用UpdateData来更新主线程中的数据。界面的东西,最好就是用主线程(界面线程)去执行相应的操作。要想在子线程(工作线程)里执行界面线程的操作,最好是向主线程发送消息。因为MFC的CWnd用到了TLS,所以不是线程安全的。

MFC的窗口是线程相关的,每个窗口的HandleMap是储存在线程相关的堆栈里面的(thread-local-storage (TLS) ),那这样我就理解了为什么上面两句ASSERT会出错了,线程环境都切换了当然线程堆栈的数据也就不一样了.

解决方法:

  在线程中发送自定义消息让主线程接收进行updatedata。

步骤:

1 在主线程对应头文件中 加入      #define WM_RECVDATA WM_USER+1

2 添加消息映射

BEGIN_MESSAGE_MAP(CChatDlg, CDialog)
  ..................
   ON_MESSAGE(WM_RECVDATA,OnRecvData)//添加这一句
 .................
END_MESSAGE_MAP() 3  在步骤1对应的头文件的
//{{AFX_MSG(CChatDlg)
         ..........
        //}}AFX_MSG
中间加入 afx_msg void OnRecvData(WPARAM wParam,LPARAM lParam);

4 定义这个函数  

void CChat::OnRecvData(WPARAM wParam,LPARAM lParam)
 {


     UpdateData(FALSE);
 

在线程中发送消息

::PostMessage(This->m_hWnd,WM_RECVDATA,0,NULL);  我把this指针传递过来给了This 所以用This直接调用主线程窗口的句柄