MFC的网络编程文档格式.docx
《MFC的网络编程文档格式.docx》由会员分享,可在线阅读,更多相关《MFC的网络编程文档格式.docx(30页珍藏版)》请在冰点文库上搜索。
![MFC的网络编程文档格式.docx](https://file1.bingdoc.com/fileroot1/2023-4/30/ee0413d7-4002-46cc-b538-00ab26e742cd/ee0413d7-4002-46cc-b538-00ab26e742cd1.gif)
));
4.
return
false;
5.}
m_iSocket是一个CServerSocket*的指针
CServerSocket类是一个我们自己的类我会在后面给出相应代码,他继承于CSocket类。
m_iSocket
new
CServerSocket();
//
1.动态创建一个服务器Socket对象。
2.
m_iSocket)
{
4.AfxMessageBox(_T("
动态创建服务器套接字出错!
5.return
6.
}
接着创建套接字
1.if(!
m_iSocket->
Create(8989))
创建套接字错误!
Close();
5.
6.}
其中8989是指定的端口号,但是要注意在保存我们指定的8989端口前,这个端口是空闲的没有被其他进程所占用,那怎么查看端口是否被其他进程占用呢?
首先打开cmd键入netstat-aon
你会看到所有的TCP/UDP信息,但是由于太多了不好查看,所以。
我们再在最下面tasklist|find“8989”
现在我们看到我们没有找到任何和8989端口相关的东西,所以说明8989端口没有被占用。
创建了套接字以后按照win32的步骤我们就应该对bind端口。
但是MFC不这样,应为MFC的Create内部已经调用了bind,如下是MFC的底层代码
CAsyncSocket:
Create(UINT
nSocketPort,
int
nSocketType,long
lEvent,
LPCTSTR
lpszSocketAddress)
if
(Socket(nSocketType,
lEvent))
(Bind(nSocketPort,lpszSocketAddress))//调用了bind
TRUE;
7.
nResult
GetLastError();
8.
9.
WSASetLastError(nResult);
10.
11.
FALSE;
12.}
所以我们不用在调用bind了,直接对套接字进行监听
Listen())
监听失败!
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
然后重载ExitInstance,退出时对进行清理
1.int
CNetChatServerApp:
ExitInstance()
3.if(m_iSocket)
4.{
5.delete
m_iSocket;
6.m_iSocket
NULL;
7.}
8.return
CWinApp:
ExitInstance();
9.}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
下面来看下CServerSocket的具体实现
1.#pragma
once
3.#include
ClientSocket.h"
5.class
CServerSocket
public
CSocket
6.{
7.public:
virtual
~CServerSocket();
10.public
CPtrList
m_listSockets;
//用来保存服务器与所有客户端连接成功后的ClientSocket
12.
13.
14.public
15.
void
OnAccept(int
nErrorCode);
16.};
1.#include
stdafx.h"
2.#include
NetChatServer.h"
ServerSocket.h"
5.CServerSocket:
CServerSocket()
8.}
10.CServerSocket:
~CServerSocket()
11.{
13.}
14.
15.void
CServerSocket:
nErrorCode)
16.{
17.
//接受到一个连接请求
18.
CClientSocket*
theClientSock(0);
19.
theClientSock
CClientSocket(&
m_listSockets);
20.
theClientSock)
21.
22.
内存不足,客户连接服务器失败!
23.
return;
24.
25.
Accept(*theClientSock);
26.
//加入list中便于管理
27.
m_listSockets.AddTail(theClientSock);
28.
CSocket:
OnAccept(nErrorCode);
29.}
我们可以看到在CServerSocket中又出现了一个CClientSocket的类,这个类和CServerSocket一样,也是派生于CSocket类,但是专门用于客户端的Socket。
在这里必须重载OnAccept(intnErrorCode)函数,这样CServerSocket才能接收到客户端的请求,并且必须在OnAccept中调用Accept()函数对连接请求进行响应。
在OnAccept()我们用一个List将ClientSocket指针保存,以便以后调用访问。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
接着我们再来看看CClientSocket类
4./////////////////////////////////////////////////
5.///说明,该类用于和客户端建立通信的Socket
6./////////////////////////////////////////////////
8.class
CClientSocket
9.{
10.public:
CClientSocket(CPtrList*
pList);
~CClientSocket();
13.public:
CPtrList*
m_pList;
//保存服务器ClientSocket中List的东西,这个是中CServerSocket中传过来的
CString
m_strName;
//连接名称
16.public:
OnClose(int
OnReceive(int
OnLogoIN(char*
buff,int
nlen);
//处理登录消息
OnMSGTranslate(char*
//转发消息给其他聊天群
UpdateServerLog();
//服务器端更新、记录日志
UpdateAllUser(CString
strUserInfo);
//更新服务器端的在线人员列表
23.private:
BOOL
WChar2MByte(LPCWSTR
srcBuff,
LPSTR
destBuff,
//多字节的转换
25.};
可以看到我们重载了OnClose()、OnReceive()函数,这样当套接字关闭、有数据到达时,就会自动调用这两个函数,我们便可以在这两个函数中响应、处理事件。
由于本人使用的是VS2010,并且采用的Unicode编码,所以,经常要涉及Unicode转多字节的情况,于是就写了WChar2MByte()进行转换
4.#include
Header.h"
5.#include
NetChatServerDlg.h"
7.CClientSocket:
pList)
m_pList(pList),m_strName(_T("
))
11.}
13.CClientSocket:
~CClientSocket()
14.{
15.}
16.
17./////////////////////////////////////////////////////////////////////
CClientSocket:
//有消息接收
//先得到信息头
HEADER
head;
nlen
sizeof
HEADER;
char
*pHead
pHead
char[nlen];
pHead)
TRACE0("
OnReceive
内存不足!
29.
30.
31.
memset(pHead,0,
sizeof(char)*nlen
32.
Receive(pHead,nlen);
33.
head.type
((LPHEADER)pHead)->
type;
34.
head.nContentLen
nContentLen;
35.
delete
pHead;
36.
37.
38.
//再次接收,这次是数据类容
39.
char[head.nContentLen];
40.
41.
42.
OnRecive
43.
44.
45.
if(
Receive(pHead,
head.nContentLen)!
=head.nContentLen)
46.
47.
接收数据有误!
48.
49.
50.
51.
////////////根据消息类型,处理数据////////////////////
52.
switch(head.type)
53.
54.
case
MSG_LOGOIN:
55.
OnLogoIN(pHead,
head.nContentLen);
56.
break;
57.
MSG_SEND:
58.
OnMSGTranslate(pHead,
59.
60.
default
61.
62.
63.
64.
OnReceive(nErrorCode);
65.
66.
67.
//关闭连接
68.
69.
70.
CTime
time;
71.
time
CTime:
GetCurrentTime();
72.
strTime
time.Format("
%Y-%m-%d
%H:
%M:
%S
73.
+
this->
m_strName
_T("
离开...\r\n"
74.
((CNetChatServerDlg*)theApp.GetMainWnd())->
DisplayLog(strTime);
75.
m_pList->
RemoveAt(m_pList->
Find(this));
76.
//更改服务器在线名单
77.
str1
78.
//通知客户端刷新在线名单
79.
UpdateAllUser(str1);
80.
81.
//销毁该套接字
82.
this;
83.
OnClose(nErrorCode);
84.
85.
86.
//登录
87.
buff,
nlen)
88.
89.
//对得接收到的用户信息进行验证
90.
//...
(为了简化这步省略)
91.
//登录成功
92.
93.
94.
95.
96.
strTemp(buff);
97.
strTemp
登录...\r\n"
98.
//记录日志
99.
100.
strTemp;
101.
//更新服务列表
102.
103.
//更新在线所有客服端
104.
105.
106.
107.//转发消息
108.
109.
110.
111.
MSG_SEND;
112.
nlen;
113.
POSITION
ps
GetHeadPosition();
114.
115.
while(ps!
=NULL)
116.
117.
pTemp
(CClientSocket*)m_pList->
GetNext(ps);
118.
pTemp->
Send(&
head,sizeof(HEADER));
119.
Send(buff,
120.
121.
122.
123.
124.
WChar2MByte(L