vc c语言多线程,多线程 + CSocket 遇到的困惑

ca56232b3bbedf9a539d07f37fffb99a.gif

3144d8b7615c79d9f638db40d5689d26.gif

a218af6549b45ee526caf607ebff1358.gif

0f8df0e29816ae721419de940fb833d1.gif

多线程 + CSocket 遇到的困惑

大侠们,偶遇到困难了,请拔刀啊!!!! 有点长,恳请看完,不吝赐教啊!!!

本人用MFC 写的一个客户端程序,分别连接两个服务端程序。

共三台计算机协作,客户端计算机为Client,两个服务端计算机为 CMDServer和DATAServer。

Client连接DATAServer 上的两个端口,这两个端口分别接受命令和发送数据。

Client接到CMDServer 发送过来的数据后,经过处理将命令转发给DATAServer。DATAServer接受到命令处理,

再给Client发送数据。Client接收到数据后存盘。

客户端程序如下描述:

这是基于对话框的应用程序。

新建三个CSocket类,三个类分别声明了一个对象,它们都是主对话框的成员变量。

CReceCMDSocket m_ReceCmdSocket;

CSendCMDSocket m_SendCmdSocket;

CReceDATASocket m_ReceDataSocket;

三个SOCKET类都重载了OnReceive函数,形式都一样,为的就是收到网络传输过来的数据时想主对话

框发送消息,如下:

void CReceCMDSocket::OnReceive(int nErrorCode)

{

SendMessage(m_hWnd,WM_RECEIVE1(WM_RECEIVE2,WM_RECEIVE3),0,0);

CSocket::OnReceive(nErrorCode);

}

定义了全局变量:

//接收一次命令也就是CMDServer向Client发送一次命令  所要接收的命令的缓冲区,

//命令接收到这里后会被COPY 到ReceCMDBuf1或ReceCMDBuf1

//一次命令长度为64字节 接收一次命令的条数不一定,但不会超过1024字节

unsigned long TempReceCMDBuf[256] = {'0'};

//命令缓存区1,CMDServer向Client发送一次命令的间隔不一定,很有可能就是连续发送(中间没有间隔时间),

//来不及处理,所以要先缓存.两个缓存区轮流被处理命令的线程扫描处理,乒乓操作

unsigned long ReceCMDBuf1[1024] = {'0'};

unsigned long ReceCMDBuf2[1024] = {'0'};        //  命令缓存区2

//指向最近一次发送的命令的末尾

unsigned long *ptHasSendCMDPosition = ReceCMDBuf1;

//指向最近一次接受的命令的末尾

unsigned long *ptReceCMDBufEnd = ReceCMDBuf1;

// 当前命令缓存区还剩下多少地方

unsigned short ReceCMDBufRemainLen = 4096;

嘿嘿,啰嗦了这么多,快到重点了。请大侠们耐心往下看,设计如果有不合理的地方,请大侠们拍砖,

我不怕疼!!!!!!!

由于数据的交换非常频繁。故使用多线程。使用临界区锁定的办法实现线程同步。现在暂时只把Client接收处理命

令的部分写完,就遇到了问题。

在主对话框的"开始"按钮的响应函数里创建了处理命令的线程。这是个WORKER线程。

//线程函数   仅仅扫描缓存区,处理和发送命令  所以做了个死循环

UINT DealReceFromWK1(LPVOID lpParamater)

{

Csocket_senddata2Dlg* pDlg = (Csocket_senddata2Dlg*)lpParamater;

while (TRUE)

{

//  ptHasSendCmdPosition 没追上  ptReceCMDBufEnd  即接收的命令 比 发送出去的命令多

if (ptHasSendCmdPosition != ptReceCMDBufEnd)

{

处理过程

}

else  //  ptHasSendCmdPosition 追上了ptReceCMDBufEnd      分两种情况

{

//情况1: ptHasSendCmdPosition 被  ptReceFromWkBufEnd 套圈了

// 接收的命令 已经 把两个缓存区装满,还没发送一条命令

if (ReceFromWKTimes > SendCmdTimes)  //

{

//提醒重启程序

}

//情况2: ptHasSendCmdPosition 追上  ptReceFromWkBufEnd   接收的命令

//暂时 和 发送出去的命令 一样多

else

{

//啥都不做

}

}

}

return 1;

}

void Csocket_senddata2Dlg::OnBnClickedBegin()   //“开始" 按钮的响应函数

{

// TODO: 在此添加控件通知处理程序代码

if(m_SendCmdSocket != NULL)

{

delete m_SendCmdSocket;

m_SendCmdSocket = NULL;

}

if(m_ReceDataSocket != NULL)

{

delete m_ReceDataSocket;

m_ReceDataSocket = NULL;

}

if(m_ReceCmdSocket != NULL)

{

delete m_ReceCmdSocket;

m_ReceCmdSocket = NULL;

}

m_SendCmdSocket = new CSendCMDSocket(m_hWnd);

m_ReceDataSocket = new CReceDATASocket(m_hWnd);

m_ReceCmdSocket = new CReceCMDSocket(m_hWnd);

if(//创建套接字 三个)

{

AfxMessageBox(_T("套接字创建失败!"));

return;

}

if(//连接 三个端口)

{

AfxMessageBox(_T("网络连接失败!"));

return;

}

else

{

AfxMessageBox(_T("网络连接成功!"));

//创建处理命令的线程

CWinThread* thread = AfxBeginThread(DealReceFromWK1, this);

}

}

//在主线程里接收命令

LRESULT Csocket_senddata2Dlg::OnMyMessage2(WPARAM,LPARAM)

{

//WaitForSingleObject(hMutex,INFINITE);

//利用临界区锁定  使得接收命令的过程不被打断,因为命令不能丢

Critical_Section.Lock();

if(m_ReceCmdSocket == NULL)

{

Critical_Section.Unlock();

//ReleaseMutex(hMutex);

return -1;

}

ReceCMDOnceLen = m_ReceCmdSocket->Receive(TempReceCMDBuf,2048);

if(ReceCMDOnceLen < 64)

{

Critical_Section.Unlock();

//ReleaseMutex(hMutex);

return -1;

}

//当前缓存区足够装下一次接受的命令

if (ReceCMDBufRemainLen >= ReceCMDOnceLen)

{

//把TempReceCMDBuf里的命令搬移到当前的缓存区

CopyMemory(ptReceCMDBufEnd,TempReceCMDBuf,ReceCMDOnceLen);

// 以下就是 计算当前缓存区还剩下多少位置 计算指针位置等

ReceCMDBufRemainLen -= ReceCMDOnceLen;

ptReceCMDBufEnd += ReceCMDOnceLen / 4;

if (ReceCMDBufRemainLen == 0)

{

ReceCMDBufRemainLen = 4096;

if ((ptReceCMDBufEnd== ReceCMDBuf2 + 1024))

{

ptReceCMDBufEnd = ReceCMDBuf1;

}

else if((ptReceCMDBufEnd == ReceCMDBuf1 + 1024))

{

ptReceCMDBufEnd = ReceCMDBuf2;

}

}

}

//当前缓存区不够装下一次接受的数据

else

{

//把缓冲区先装满

CopyMemory(ptReceCMDBufEnd,TempReceCMDBuf,ReceCMDBufRemainLen);

ptReceCMDBufEnd += ReceCMDBufRemainLen / 4;

if ((ptReceCMDBufEnd == ReceCMDBuf2 + 1024))

{

ptReceCMDBufEnd = ReceCMDBuf1;

}

else if((ptReceCMDBufEnd == ReceCMDBuf1 + 1024))

{

ptReceCMDBufEnd = ReceCMDBuf2;

}

CopyMemory(ptReceCMDBufEnd,TempReceCMDBuf + ReceCMDBufRemainLen,ReceCMDOnceLen - ReceCMDBufRemainLen);

ptReceCMDBufEnd += (ReceCMDOnceLen - ReceCMDBufRemainLen) / 4;

ReceCMDBufRemainLen = 4096 - ReceCMDOnceLen + ReceCMDBufRemainLen;

}

//临界区解除锁定

Critical_Section.Unlock();

//ReleaseMutex(hMutex);

return 1;

}

问题:

1、因为CMDServer 发送命令的速度非常快,会发生这样的情况,还在搬移命令到缓存区到

过程中(这个过程被临界区锁定),又发送了一次命令。这样肯定会丢命令的。不知道说的对不对?

如果是这样, 如何解决?

2、现在还没有写接收DATAServer 数据的代码,一旦写了,DATAServer 一次发送的数据量

很大,数据又不能丢,接收的过程不能中断,所以必须使用临界区锁定住。到时还会发生这样

的情况,正在接收DATAServer数据的时候,CMDServer发送来了命令。那么这个命令肯定丢了。

如果是我说的这样,该如何解决?

两个问题,请大侠们一定赐教,感激不尽。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值