//API版
// 服务器端程序:
// 1、加载套接字库WSAStartup 环境初始化
// 2、创建套接字(socket)。
// 3、将套接字绑定到一个本地地址和端口上(bind)。
// 4、将套接字设为监听模式,准备接收客户请求(listen)。
// 5、等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。
// 6、用返回的套接字和客户端进行通信(send/recv)。
// 7、返回,等待另一客户请求。
// 8、关闭套接字。
// 9、清理套接字环境,释放资源WSACleanup
MFC版:
1、 套接字环境初始化 AfxSocketInit
2、创建套接字对象Create
3、 绑定IP地址及端口Create
4、 监听 Listen5、 等待请求到来: 重写OnAccept虚函数,接收相应消息,(然后调用Accept成员函数返回 客户端套接对象)
6、 消息分发处理 :重写OnReceive虚函数,接收相应消息,(然后调用Receive成员函数返回消息);发送时,直接调用成员函数Send
客户端:
1、 套接字环境初始化 AfxSocketInit
2、创建套接字对象Create
3、 绑定IP地址及端口Create
4、 监听 Listen
5、 消息分发处理 :重写OnReceive虚函数,接收相应消息,(然后调用Receive成员函数返回消息);发送时,直接调用成员函数Send
//1、 套接字环境初始化 AfxSocketInit
WSADATA data;
if (AfxSocketInit(&data))//AfxSocketInit返回值非零表示成功
{
TRACE("AfxSocketInit 初始化成功\n");
}
class CCSocket_ServerDlg;
class CMySocket : public CSocket
{
public:
CMySocket();
virtual ~CMySocket();
virtual void OnClose(int nErrorCode);
virtual void OnReceive(int nErrorCode);
virtual void OnAccept(int nErrorCode);
void setDlg(CCSocket_ServerDlg * Dlg);
private:
CCSocket_ServerDlg * m_pDlg;
};
.cpp
// MySocket.cpp : 实现文件
//
#include "stdafx.h"
#include "CSocket_Server.h"
#include "MySocket.h"
#include "CSocket_ServerDlg.h"
// CMySocket
CMySocket::CMySocket()
{
}
CMySocket::~CMySocket()
{
}
// CMySocket 成员函数
void CMySocket::OnClose(int nErrorCode)
{
if (nErrorCode == 0)
{
m_pDlg->OnClose();
}
return;
}
void CMySocket::OnReceive(int nErrorCode)
{
if (nErrorCode == 0)
m_pDlg->OnReceive();
return;
}
void CMySocket::OnAccept(int nErrorCode)
{
if (nErrorCode == 0)
m_pDlg->OnAccept();
return;
}
void CMySocket::setDlg(CCSocket_ServerDlg * Dlg)
{
m_pDlg = Dlg;
}
是为了将他们能够在一个.cpp文件中编写。
PS:我们自己新建的CMySocket类是连接CSocket类和主窗口类(CCSocket_ServerDlg)的。
//2、创建套接字对象Create 3、 绑定IP地址及端口Create 4、 监听 Listen
UpdateData(true);//从窗口获取数据
BOOL flag = m_ServerSocket.Create(m_nPort);//创建套接字,绑定端口,IP
if (flag)
{
TRACE("create and bind successful");
if (m_ServerSocket.Listen())
{
TRACE("listen successful");
}
}
//5、 等待请求到来 OnAccept 、Accept 6、 消息分发处理 OnReceive、Receive
添加
CMySocket m_ServerSocket;//服务器套接字
CMySocket m_ClientSocket;//新连接的客户端套接字
void OnClose(void);
void OnReceive(void);
void OnAccept(void);
void CCSocket_ServerDlg::OnClose(void)
{
m_ServerSocket.Close();
m_ClientSocket.Close();
}
void CCSocket_ServerDlg::OnReceive(void)
{
char* pBuf[1025] = { 0 };
int nBuffSize = 1024;
int r = m_ClientSocket.Receive(pBuf, nBuffSize);
if (r != SOCKET_ERROR)
{
//具体代码
UpdateData(false);
}
else
{
AfxMessageBox(_T("数据接收错误!"), MB_OK | MB_ICONSTOP);
return;
}
}
void CCSocket_ServerDlg::OnAccept(void)
{
m_ServerSocket.Accept(m_ClientSocket); //获取新连接对象即可
}
注意:此处调用的是CSocket的Accept、Receive、Close函数。
在.cpp中// TODO: 在此添加额外的初始化代码
m_ServerSocket.setDlg(this);
m_ClientSocket.setDlg(this);
//6、 消息分发处理 Send
UpdateData(true);
if (!m_strMsg.IsEmpty()) //判断msg编辑框是否为空
{
m_ClientSocket.Send(LPCTSTR(m_strMsg.GetString()), 2 * m_strMsg.GetLength()); //发送消息
m_listSend.AddString(m_strMsg); //添加到列表中
m_strMsg.Empty(); //清空编辑框
UpdateData(false);
}
新建一个CSocket_Client的项目。
注意:客户端不需要重写OnAccept
//2、创建套接字对象Create 3、 绑定IP地址及端口Create 4、 监听 Listen
UpdateData(true);
if (m_ClientSocket.Create())
{
if (m_ClientSocket.Connect(m_strIP, m_nPORT))
{
TRACE("link server successful");
}
}
将其更改为一下:
注:可有.send获得发送的字节数
int sendlen=myClientSocket.Send(m_strMsg,m_strMsg.GetLength()*2);
TRACE("成功发送%d 字节\n",sendlen);
此时,服务器和客户端可相互通信。
代码:CSocket_Server.zip
①客户端不需要重写OnAccept
②客户端的链接(即create、connect)和服务器的链接(create、listen)不一样
③注意重写窗口销毁函数,调用 OnClose();函数
④为了防止误操作,注意按钮的禁用(button.EnableWindow(false);)和使用(button.EnableWindow(true);)