一个socket源码

VC编写服务器转发式的聊天室

2009-9-11  本文参考了 Visual C++6.0完全自学手册 中的示例

一 流程说明
客户端
客户端创建流式套接字
调用Connection向服务器发送连接请求
连接成功后使用创建与之关联的的CSocketFile对象和CArchive对象
使用CArchive对象在客户端和服务器之间传送数据
结束之后释放CSocketFile对象,CArchive对象,CSocket对象

服务端
服务端创建流式套接字
开始监听连接请求
有连接请求调用Accpet函数接受请求,并创建一个新的客户端套接字。
连接成功后使用创建与之关联的的CSocketFile对象和CArchive对象
使用CArchive对象在客户端和服务器之间传送数据。
服务端接受到某一个客户端发送过来的数据之后,将数据发送到连接到该服务器的各个客户端
结束之后释放CSocketFile对象,CArchive对象,CSocket对象

二 重载函数说明
客户端Clientsocket需要重载virtual void OnReceive(int nErrorCode);和virtual void OnClose(int nErrorCode);函数
服务端需要重载virtual void OnAccept(int nErrorCode);函数


三 实现
1消息文本串行化操作类
头文件Msg.h
class CMsg : public CObject 
{
public:
 void Serialize(CArchive& ar);
 CString m_strMsg;
 CMsg();
 virtual ~CMsg();

};
实现文件Msg.cpp
#include "stdafx.h"
#include "Msg.h"
CMsg::CMsg()
{
 m_strMsg = _T(""); 
}
CMsg::~CMsg()
{
}

void CMsg::Serialize(CArchive &ar)
{
 if (ar.IsStoring())
  ar << m_strMsg;
 else
  ar >> m_strMsg;
}


2 客户端Socket类
头文件ClientSocket.h
#include "stdafx.h"
#include   "afxsock.h"
class CMsg;
class CClientSocket : public CSocket
{
public:
 CSocketFile * m_pSocketFile;
 CArchive * m_pArchiveIn;
 CArchive * m_pArchiveOut;
 bool m_bClose;
public:
 CClientSocket();
 virtual ~CClientSocket();
public:
 void SendMsg(CMsg * pMsg);
 void Init();
 public:
 virtual void OnReceive(int nErrorCode);
 virtual void OnClose(int nErrorCode);
protected:
};
实现文件ClientSocket.cpp
#include "stdafx.h"
#include "ClientSocket.h"
#include "Msg.h"
CClientSocket::CClientSocket()
{
 m_pArchiveIn = NULL;
 m_pArchiveOut = NULL;
 m_pSocketFile = NULL;
 m_bClose = FALSE;
}

CClientSocket::~CClientSocket()
{
 if(m_pArchiveIn)
  delete m_pArchiveIn;
 if(m_pArchiveOut)
  delete m_pArchiveOut;
 if(m_pSocketFile)
  delete m_pSocketFile;
 m_pArchiveIn = NULL;
 m_pArchiveOut = NULL;
 m_pSocketFile = NULL;
 m_bClose = TRUE;
}


void CClientSocket::Init()
{
 m_pSocketFile = new CSocketFile(this);
 m_pArchiveIn = new CArchive(m_pSocketFile, CArchive::load);
 m_pArchiveOut = new CArchive(m_pSocketFile, CArchive::store);
 m_bClose = FALSE;

}

void CClientSocket::OnReceive(int nErrorCode)
{
 

 do
 {
  CMsg msg;
  msg.Serialize(*m_pArchiveIn);
这里主要处理接受的数据
 
 }
 while (!m_pArchiveIn->IsBufferEmpty());
 CSocket::OnReceive(nErrorCode);
}

void CClientSocket::SendMsg(CMsg * pMsg)
{
 if (m_pArchiveOut != NULL)
 {
  pMsg->Serialize(*m_pArchiveOut);
  m_pArchiveOut->Flush();
 }
}
void CClientSocket::SendMsg(CMsg * pMsg)
{
 if (m_pArchiveOut != NULL)
 {
  pMsg->Serialize(*m_pArchiveOut);
  m_pArchiveOut->Flush();
 }
}
void CClientSocket::OnClose(int nErrorCode)
{
 m_bClose = TRUE;
 CSocket::OnClose(nErrorCode);
}
3服务器不仅要包括客户端socket,串行化数据还需要一个监听Socket
头文件ServerSocket.h
#pragma once
#include "stdafx.h"
#include "afxsock.h"
class CServerDlg;

class CServerSocket : public CSocket
{
public:
 CServerSocket();
 virtual ~CServerSocket();
public:
 void Init(UINT port);
 UINT m_uPort;
 public:
 virtual void OnAccept(int nErrorCode);

};
实现文件ServerSocket.cpp
#include "stdafx.h"
#include "ServerSocket.h"
#include "ClientSocket.h"
#include "afxsock.h"
#include "Msg.h"
CServerSocket::CServerSocket()
{
}

CServerSocket::~CServerSocket()
{
}

void CServerSocket::Init(UINT port)
{
 m_uPort = port;

 this->Create(m_uPort);  // 创建服务器套接字
 this->Listen();  // 开始监听连接请求


}

void CServerSocket::OnAccept(int nErrorCode)
{


 //在这里将数据库变化的通知发送到各个服务端或者采用回调函数处理
 CSocket::OnAccept(nErrorCode);
}

在OnAccept处理函数中将消息发送到各个客户端
CPtrList m_plConn; //链表类存储接受的客户端socket
CServerSocket  m_ListenSocket;
 CClientSocket * pSocket = new CClientSocket();// 新建客户端套接字
 if (m_ListenSocket.Accept(*pSocket))// 接受连接请求
 {
  CMsg msg;
  msg.m_strMsg = L"收到消息";
  for(POSITION pos=m_plConn.GetHeadPosition(); pos!=NULL;)
  { // 向客户端套接字发送消息对象
   CClientSocket * s = (CClientSocket *)m_plConn.GetNext(pos);
   s->SendMsg(&msg);
  }
  pSocket->Init();/ 新客户端套接字初始化
  m_plConn.AddTail(pSocket);// 添加到已连接套接字列表中
 
 }
 else
 {
  delete pSocket;
 }
}

以上程序已经在Visual C++2005  中调试通过

发表于 @ 2009年09月11日 01:43:00 | 评论( 0 ) | 编辑| 举报| 收藏

旧一篇:在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除。 | 新一篇:简单而强大的可调整大小对话框(Simple and more powerful resizable dialog)
查看最新精华文章 请访问博客首页相关文章
关于如何解决C++ Builder中DBLookupComboBox不能输入的问题:在客户端使用智能指针的COM_自己弄个简单的智能指针ACE proactor example策略模式(STRATEGY)案例分析工厂方法模式C++实现设计模式的实现(C++)------抽象工厂模式(AbstractFactory)我的C++实践(3):用多态机制来做设计ICE的异步方法调用

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/flyfish1986/archive/2009/09/11/4541008.aspx

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值