336上位机VC MFC用套接字编写聊天室
用套接字编写聊天室
功能展示
利用套接字可以方便快速编写网络程序,我们当前例程利用套接字编写一网络聊天室程序,效果如图,首先启动服务器例程,然后就可以启动多个客户端程序连接服务器,各个客户端间就可以自由聊天。例程展示了利用套接字编写网络程序的顺序,方便大家学习;
要点提示
Csocket类对窗口SOCKET API函数进行了高层次的封装,可以同步操作,可以单独使用,可以与CSocketFile,Carchive类一起实现数据的发送与接收。我们来介绍下Csocket类的主要函数;
Create()函数用于创建一个套接字。 BOOL Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, LPCTSTR lpszSocketAddress = NULL ); nSocketPort 为套接字的端口, nSocketType 套接字的类型, lpszSocketAddress 确定套接字的IP地址;
Listen ()用于监听套接字的连接请求。
BOOL Listen( int nConnectionBacklog = 5 ); nConnectionBacklog 表示连接最大队列长度;
Send()用于发送数据到连接的套接字上;
virtual int Send( const void* lpBuf, int nBufLen, int nFlags = 0 ); lpBuf为发送数据的缓冲区; nBufLen缓存区的大小。 nFlags 确认函数的调用模式;
Receive ()用于从套接字上接收数据;
virtual int Receive( void* lpBuf, int nBufLen, int nFlags = 0 ); lpBuf为接收数据的缓冲区; nBufLen缓存区的大小。 nFlags 确认函数的调用模式;
实现功能
1.新建基于对话框的应用程序,用于服务器程序的实现;
2.从CSocket类派生一新类CClientSocket,添加一主对话框指针变量public:CGkbc8Dlg *m_pDlg,再修改类的构造函数初始化此变量再添加一接收数据的虚函数
void CClientSocket::OnReceive(int nErrorCode)
{
if(m_pDlg)
{
//调用对话框的ReceiveData方法
m_pDlg->ReceiveData(this);
}
CSocket::OnReceive(nErrorCode);
}
3.从CSocket类派生一新类CServerSocket,添加一主对话框指针变量public:CGkbc8Dlg *m_pDlg,再修改类的构造函数初始化此变量再添加一接收连接的虚函数
void CServerSocket::OnAccept(int nErrorCode)
{
if (m_pDlg)
m_pDlg->AcceptConnect();
CSocket::OnAccept(nErrorCode);
}
4.在主对话框中包含两个类的头文件#include “ServerSocket.h“ #include ”ClientSocket.h”,再添加两变量及两函数 void AcceptConnect();
void ReceiveData(CClientSocket *pSocket);
CServerSocket* m_pServerSocket;
CPtrList m_socketlist;
void CGkbc8Dlg::AcceptConnect()
{
CClientSocket* socket = new CClientSocket(this);
if (m_pServerSocket->Accept(*socket))//接受客户端的连接
m_socketlist.AddTail(socket);
else
delete socket;
}
void CGkbc8Dlg::ReceiveData(CClientSocket* pSocket)
{
char bufferdata[250];
int result = pSocket->Receive(bufferdata,250);//接收客户端传来的数据
bufferdata[result] = 0;
POSITION pos = m_socketlist.GetHeadPosition();
while (pos!=NULL)//将数据发送给每个客户端
{
CClientSocket* socket = (CClientSocket*)m_socketlist.GetNext(pos);
if (socket != NULL)
socket->Send(bufferdata,result);
}
}
5.依照例程界面,添加两编辑框IDC_EDIT1, IDC_EDIT2,一按钮<开始监听>关联按钮点击函数
void CGkbc8Dlg::OnStart()
{
m_pServerSocket = new CServerSocket(this);
if (!m_pServerSocket->Create(1026))
{
MessageBox("套接字创建失败");
delete m_pServerSocket;
m_pServerSocket = NULL;
return;
}
if (!m_pServerSocket->Listen())
MessageBox("监听失败");
}
6.程序初始化时实现化套按字
WSADATA wsd;
AfxSocketInit(&wsd);//初始化套接字库
DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
char Buffer[MAX_COMPUTERNAME_LENGTH + 1];
GetComputerName(Buffer,&nSize);
CString str;
str.Format("服务器名称:%s",Buffer);
SetDlgItemText(IDC_EDIT1,str);
SetDlgItemText(IDC_EDIT2,"服务器端口号:1026");
7.再新建一对话框应用程序,用于聊天程序的实现;
8.从CSocket类派生一新类CChatSocket ,添加一主对话框指针变量CChaterDlg *m_pChatDlg; ,再修改类的构造函数初始化此变量再,添加一接收数据的虚函数
void CChatSocket::OnReceive(int nErrorCode)
{
if(m_pChatDlg)
m_pChatDlg->ReceiveData();
CSocket::OnReceive(nErrorCode);
}
9.在主对话框中添加一函数及类的实例变量public: void ReceiveData(); CChatSocket *m_pChatSocket;
void CChaterDlg::ReceiveData()//接收到信息
{
char buffer[250];
int factdata = m_pChatSocket->Receive(buffer,250);//接收传来的数据
buffer[factdata] = '\0';
CString str;
str.Format("%s",buffer);
CListBox *pListBox = (CListBox*)GetDlgItem(IDC_LIST1);
pListBox->InsertString(pListBox->GetCount(),str);//将数据添加到列表框中
}
10. 依照界面添加三编辑框IDC_EDIT1, IDC_EDIT2, IDC_EDIT3,一列表框控件IDC_LIST1,两按钮控件<连接到服务器><发送信息>关联两按钮点击函数
void CChaterDlg::OnButton1() //连接到服务器
{
CString sServerName,sNickName;
GetDlgItemText(IDC_EDIT1,sNickName);//聊天用网名
GetDlgItemText(IDC_EDIT2,sServerName);//读取服务器名称
if(sNickName.IsEmpty()||sServerName.IsEmpty())
return;
int port = 1026; //服务器端口
if (!m_pChatSocket->Connect(sServerName,port)) //连接服务器
{
MessageBox("连接服务器失败!");
return;
}
CString str;
str.Format("%s----->%s",sNickName,"进入聊天室");
m_pChatSocket->Send(str.GetBuffer(0),str.GetLength());
}
void CChaterDlg::OnSend()
{
CString sText,sNickName,temp;
GetDlgItemText(IDC_EDIT3,sText);
GetDlgItemText(IDC_EDIT1,sNickName);
if (sText.IsEmpty()|sNickName.IsEmpty())
return;
temp.Format("%s说: %s",sNickName,sText);
m_pChatSocket->Send(temp.GetBuffer(temp.GetLength()),temp.GetLength());
SetDlgItemText(IDC_EDIT3,"");
GetDlgItem(IDC_EDIT3)->SetFocus();
}
11.最后是在程序初始化时初始化套接字
我们来演示下功能实现的整个过程
如果您认可,可联系功能定制! 如果您着急,充值会员可直接联系发您资料!
|