在mfc中如何设计基于tcp的同时支持多客户端的服务器程序?

madhappy 2004-05-06 05:19:40
我希望用同一个端口,因为如果客户机不确定我主机的端口会很麻烦。

本来的设计是来一个请求就多一个连接。然后接受数据,把数据放在一个队列里面,由一个线程来处理数据,并等数据完成后,把数据传回去。

下面是我自定义的两个继承于Csocket的类。,然后在我的主线程中我该如何使用?

class ServerSocket : public CSocket

public:
ServerSocket();
virtual ~ServerSocket();

public:

public:
virtual void OnReceive(int nErrorCode);
virtual void OnClose(int nErrorCode);

void SetPossessor(CRate_ServerDlg* pDlg); //这个是获得对话框指针
无关紧要的
void Finish_Comm();//释放指针用的
void SentData(CString strMsg);//发送数据的函数(写缓冲区)
NetData ReceiveData(); //接受数据的函数(读缓冲区)
void Init(); //初始化

protected:
CArchive *m_pArOut;
CArchive *m_pArIn;
CSocketFile *m_pFile;
CRate_ServerDlg *m_pDlg;//对话框指针
};
class ClistenSocket : public CSocket //这个类主要是负责生成监听变量的。
{

public:


public:
ClistenSocket();
virtual ~ClistenSocket();

public:
public:
virtual void OnAccept(int nErrorCode);

void SetPossessor(CRate_ServerDlg *pDlg); //和上面一个意思。

protected:

CRate_ServerDlg *m_pDlg;
};
...全文
141 14 点赞 打赏 收藏 举报
写回复
14 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
fantasychina 2004-05-11
也可以这样实现:
在C**Socket.cpp中
void C**Socket::OnAccept(int nErrorCode)
{
if(nErrorCode==0)
pDlg->OnAccept(this);
}
在C**Dlg.cpp中
void C**Dlg::OnAccept(C**Socket *pSocket)
{
pSocket=new C**Socket;
pSocket->SetProcesser(this);
if(m_ListenSocket.Accept(pSocket)!=SOCKET_ERROR)
{
m_SocketList.AddTail(pSocket) //CPtrList m_SocketList;
}
}
当要用时
POSITION pos=m_SocketList.GetHeadPos()
while(pos!=NULL)
{
C**Socket *m_pSocket=(C**Socket*)m_SocketList.GetNext(pos);
m_pSocket.Send(lpBuf,nLength);
}
  • 打赏
  • 举报
回复
bplinux 2004-05-10
CSocket 你不用自己处理线程吧?
同意Eearbird(early_bird)的说法。
在Listensocket的 onaccept中 生成一serversocket对象,然后ListenSocket::Accept(*pServersocket) 就可以了,当然可以把pserversocket放在你
所指的管理队列中,分配id也可以(如用一static变量)。
然后的事情是对应的pserversocket和客户通讯,在pserversocket的onreceive和send
中处理。
不知道这么说有没有理解你的意思。
附: 固定数量客户处理
void CProperty5Dlg::ProcessAccept()
{
CString csSockAddr;
CString csInfo;

UINT nSockPort;
for(int i=0;(i<MAXCLIENTS)&&(m_clientSockets[i].m_used == 1);i++) ;

if(i == MAXCLIENTS)
{
AfxMessageBox("达到最大连接数");
m_page1.m_list1.AddString("达到最大连接数,不能接受用户");
return;
}

CClientSocket* pSocket = &m_clientSockets[i];
pSocket->m_used = 1;


if (m_MySocket.Accept(*pSocket))
{
if(pSocket->GetSockName(csSockAddr, nSockPort)){
CTime t = CTime::GetCurrentTime();
CString strNow = t.Format("%H:%M:%S");
CString adress;
adress.Format("%0x",pSocket);
csInfo.Format("%s %s 连接,使用socket内存地址0X%s,等待验证...", strNow, csSockAddr,adress);

m_page1.m_list1.AddString(csInfo);
}
}
else
{
pSocket->m_used = 0;
}
}
  • 打赏
  • 举报
回复
madhappy 2004-05-10
这个程序那天晚上我就弄好了,不过很感谢大家发言。下面是我的代码。不足之处请指正。因为这种代码我没写过。感觉是靠想象力写出来得……见笑。

过几天再结贴。

void CRate_ServerDlg::ProcessAccept()
{
static Id=0;
ListCtrlData listdata; //链表节点数据的核心是这个ListCtrlData结构
CString Addr;
UINT Port;
CString a;
a.Format("%d",Id);
p_ServerSocket=new ServerSocket(); //生成一个新的套接字对象并初始化
p_ServerSocket->SetPossessor(this);
m_listensocket.Accept(*p_ServerSocket);
p_ServerSocket->Init();
p_ServerSocket->GetPeerName(Addr,Port);
p_ServerSocket->SocketId=Id; //给这个套接字连接分配一个唯一的id
listdata.p_socket=p_ServerSocket;//往结构填数据,数据中最重要的就是这个指针
listdata.id=a;
listdata.ip=Addr;
a.Format("%d",Port);
listdata.port=a;
listdata.action="CONNECT";
quene.EnterQueue(listdata); //将连接加入到对列尾部
Id++;//id值递增
ShowData();//这个是要屏幕上显示的信息。
}
  • 打赏
  • 举报
回复
madhappy 2004-05-10
jiudon(大猫) ( )

Csocket本身就是一个wsaasynchroselect i/o模型
这个被mfc采纳的模型本来不是用多线程来完成的。
如果需要多线程,那就应该使用重叠io和完成端口来做
  • 打赏
  • 举报
回复
whiteclouds 2004-05-10
mfc里有个例子程序,自己看看吧.
  • 打赏
  • 举报
回复
williamxia8 2004-05-10
MFC的socket默认支持多客户端,只要你接收就可以了
  • 打赏
  • 举报
回复
sosoxman 2004-05-10
简单描述一下。
//定义一个结构存放socket及thread
typedef struct tagSocketItem{
CYourSocket *pSocket;
CWinThread *pThread;
}tSocketItem, *ptSocketItem

//变量
CPtrList m_ClientSocketList;
CCriticalSection m_ClientSocketListLock;

// OnAccept 当收到连接时,保存socket对象,同时启动一个消息处理线程,等待消息
……
ptSocketItem pSocketItem;
……
CYourSocket *pSocket = new CYourSocket;
if(this->Accept(&pSocket))
{
m_ClientSocketListLock.Lock();
try{
pSocketItem.pSocket = pSocket;
pSocketItem.pThread = AfxBeginThread(ProcMsgThread, pSocketItem);
m_ClientSocketList.AddTail(pSocketItem);
}catch(...){
}
m_ClientSocketListLock.UnLock();
AfxBeginThread
}else{
// deal with error
}

……

// OnReceive
……
//找出是哪个socket收到消息
pSocketItem->pThread->ResumeThread();
//

// 消息接收处理线程
UINT ProcMsgThread(LPVOID lpParam)
{
ptSocketItem pSocketItem = (ptSocketItem)lpParam;
while(1)
{
……
pSocketItem->pSocket->Receive(pBuf, iBufSize);
// 处理消息过程,可以另启一个线程
pSocketItem->pThread->SuspendThread();
}
}
  • 打赏
  • 举报
回复
jiudon 2004-05-10
怎么不用线程来完成!

动态的创建线程,只要所创建的线程被连接就再创建新的线程
监听等待连接?!!!
  • 打赏
  • 举报
回复
madhappy 2004-05-08
事实上我需要在连接请求中,自行生成一个serversocket的指针,并在堆中产生空间进行数据交互,然后我把他的地址放在一个链表中,这个链表还包含其他信息,比如给这个连接分配一个ID。方便于我管理。不是很难,也没那么简单。

书我不是没看过,只是具体代码没写过。发现现在CSDN中人才真的很少啊……
  • 打赏
  • 举报
回复
Eearbird 2004-05-08
"那么我在onaccept()函数中建立线程"
没错,可以这样处理(尽管这种方法很不好)

"但是第二个连接请求来了,我怎么办?listensocket.listen();这行代码还在继续监听吗?"
监听的socket当然还在监听.

"第二个连接来了以后,我需要再生成一个,serversocket?"
新的请求来了之后,当然会生成一个新的连接socket进行通信.

建议你仔细看看socket编程方面(最好是介绍socket api的)的书,再来用CSocket的类
  • 打赏
  • 举报
回复
madhappy 2004-05-07
贴子晾在这一天了……没有人能解决吗?
  • 打赏
  • 举报
回复
zhaolaoxin 2004-05-07
MFC的socket默认支持多客户端
  • 打赏
  • 举报
回复
madhappy 2004-05-06
我的代码是这样的
listensocket.Creat(PORT);
listensocket.listen();

那么我在onaccept()函数中建立线程?

如果只有一个连接,这样当然没问题,不建立线程也可以阿。

但是第二个连接请求来了,我怎么办?listensocket.listen();这行代码还在继续监听吗?

在onaccept()中,我需要使用listensocket.Accept(serversocket);用这个变量来和客户端进行通讯。
第二个连接来了以后,我需要再生成一个,serversocket?
  • 打赏
  • 举报
回复
yhqs540 2004-05-06
用线程模式处理,接受到一个请求就建立一个thread,用队列组织线程
  • 打赏
  • 举报
回复
相关推荐
发帖
网络编程
加入

1.8w+

社区成员

VC/MFC 网络编程
申请成为版主
帖子事件
创建了帖子
2004-05-06 05:19
社区公告
暂无公告