乐之者体感开发

好知者不如乐之者,体感开发请点击:http://www.enjoythis.net/

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

 

 

老师的作业,让做一个局域网聊天室!看了孙鑫的视频!自己也简单的实现了一下!感觉挺棒的!

一个中心-----"练习"

下面贴出自己的简单理解,告诉自动掠过,,,,,,,,,

聊天室基于UDP协议,

1.套接字初始化

AfxSocketInit()函数初始化 

1     if(!AfxSocketInit())
2 {
3 AfxMessageBox("加载套接字失败库!");
4 return FALSE;
5 }
 

 套接字初始化完成,当然我们得在预编译头文件里面将AfxSocketInit()所需的头文件包含进来,否则他不认识的!

 

1 #include <afxsock.h>  //stdfax.h中的

 

BOOL CNetworkDlg::InintScoket()
{
	m_scoket=socket(AF_INET,SOCK_DGRAM,0); //自己要做的工作-----定义私有变量成员
	if(INVALID_SOCKET==m_scoket)
	{
		MessageBox("套接字创建失败");
		return FALSE;
	}
		SOCKADDR_IN addrSock;
		addrSock.sin_family=AF_INET;
		addrSock.sin_port=htons(6000);
		addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY) ;
		int reval;
		reval=bind(m_scoket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
		if(SOCKET_ERROR==reval)
		{
			closesocket(m_scoket);
			MessageBox("绑定失败!");
			return FALSE;
		}
	
	return TRUE;

	
}

  这样我们就可以在OnInitDialog()里面调用了;

2.接收端 

接收端由于要处理实时消息,所以单独做出一个线程来处理!我们来看一下MSDN的解释:

CreateThread
The CreateThread function creates a thread to execute within the virtual address space of the calling process. 

To create a thread that runs in the virtual address space of another process, use the CreateRemoteThread function. 

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
  DWORD dwStackSize,                        // initial stack size
  LPTHREAD_START_ROUTINE lpStartAddress,    // thread function
  LPVOID lpParameter,                       // thread argument
  DWORD dwCreationFlags,                    // creation option
  LPDWORD lpThreadId                        // thread identifier
);

以上函数,各个参数我就这里不解释了(具体我其实不知道看孙鑫十五课)第三个参数是我们关注的对象!只能传进去一个参数!然而我们想处理的却有两个:套接字和窗口句柄!

我们注意到这是一个指针!所以我们做一个结构体将其作为指针传进得到两个值

1 struct RECEPARAM
2 {
3 SOCKET socket;
4 HWND hwnd;
5 };

然后放到OnInitDialog()调用CreateThread()得到其句柄

1     RECEPARAM *pReceParam=new RECEPARAM;
2 pReceParam->socket=m_scoket;
3 pReceParam->hwnd=m_hWnd;
4 HANDLE hThread=CreateThread(NULL,0,ReceProc,(LPVOID)pReceParam,0,NULL); //注意到Rece是线程创建的函数!
5 CloseHandle(hThread);


下面写先从创建函数!ReceProc();

 1 DWORD WINAPI  CNetworkDlg::ReceProc(LPVOID lpParameter)
2 {
3 SOCKET sock=((RECEPARAM*)lpParameter)->socket;
4 HWND hwnd=((RECEPARAM*)lpParameter)->hwnd;
5
6 //接收数据
7 SOCKADDR_IN addr_form;
8 int len=sizeof(SOCKADDR);
9 char recBuf[200];
10 char tempBuf[300];
11
12 int retval;
13 while(TRUE)
14 {
15 retval=recvfrom(sock,recBuf,200,0,(SOCKADDR*)&addr_form,&len);
16 if ( SOCKET_ERROR ==retval)
17 {
18 break;
19 }
20 sprintf(tempBuf,"%s 说: %s",inet_ntoa(addr_form.sin_addr),recBuf);
21 ::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
22 }
23
24
25 return 0;
26 }

整个程序运行起来,线程就不断的跑了(while(true))!

当来消息时,怎么办呢?

下面是消息处理函数:

1     afx_msg void OnRecvData(WPARAM wParam,LPARAM lParam); //声明为私有函数

 

 1  void CNetworkDlg::OnRecvData(WPARAM wParam,LPARAM lParam)
2 {
3
4 CString str=(char*)lParam;
5 CString strTemp;
6 GetDlgItemText(IDC_EDIT_RECE,strTemp);
7 str+="\r\n";
8 str+=strTemp;
9 SetDlgItemText(IDC_EDIT_RECE,str);
10 }

这样就能处理了.......

下面类看一下界面吧(开始就该设计好的)

当要点击发送时要完成的工作:获取IP,保存并传入内容,送过去让线程捕获!

双击界面“发送”

 1 void CNetworkDlg::OnBtnSend() 
2 {
3 // TODO: Add your control notification handler code here
4 DWORD dwip;
5
6 ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS2))->GetAddress(dwip);
7 SOCKADDR_IN addrTo;
8 addrTo.sin_family=AF_INET;
9 addrTo.sin_port=htons(6000);
10 addrTo.sin_addr.S_un.S_addr=htonl(dwip) ;
11
12 CString strSend;
13 GetDlgItemText(IDC_EDIT2,strSend);
14 sendto(m_scoket,strSend,strSend.GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR));
15 SetDlgItemText(IDC_EDIT2,"");
16
17 }


好了,发送过去了,正在跑动的线程一捕获,立马显示给编辑框!

我实验了一下,有个bug,看不到自己的发送内容(明明保存了内容怎么就消失了呢?)

自己给自己发可以,两台电脑上有问题!摸索中,,,,,,,,

 

 



 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2011-11-17 09:18  伟征  阅读(3842)  评论(1编辑  收藏  举报