科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件锁定模式下的非锁定实现

锁定模式下的非锁定实现

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

锁定模式下为了避免socket在进行IO操作时一直处于“凝固”状态,简单地用两个线程来实现:一个线程用于数据的接收;另一个线程则用于对接收到的数据进行相关的处理。因为由两个线程来实现。

作者:Lanno Ckeeke 来源:CSDN 2008年3月20日

关键字: 实现 锁定 C++ C Linux

  • 评论
  • 分享微博
  • 分享邮件

说明

锁定模式下为了避免socket在进行IO操作时一直处于“凝固”状态,简单地用两个线程来实现:一个线程用于数据的接收;另一个线程则用于对接收到的数据进行相关的处理。因为由两个线程来实现,其特点:

<!--[if !supportLists]-->     <!--[endif]-->对数据的处理可以是耗时操作,它不会对数据的接收带来影响。

<!--[if !supportLists]-->     <!--[endif]-->对数据的接收与处理分别在不同的线程内,故应考虑数据的完整性,应避免在数据接收完全之前就对数据进行操作,可以以多种方式实现:如Mutex,Semphore,CriticalSection等同步技术。

<!--[if !supportLists]-->     <!--[endif]-->当数据接收完全之后,还需要及时的通知另一个线程,以便及时处理。其实现方法是:当接收完数据后,发送已完成信号。

详细说明参见<Windows网络编程>一书。

本代码中应用CriticalSectionevent来实现。

需要注意的是:event为自动重置

完整代码及注释

// zBlogSocket.cpp : 定义控制台应用程序的入口点。

//

//多线程socket锁定

<!--[if !supportEmptyParas]--> <!--[endif]-->

#include "stdafx.h"

#include <WinSock2.h>

#include <Windows.h>

#include <iostream>

using namespace std;

<!--[if !supportEmptyParas]--> <!--[endif]-->

CRITICAL_SECTION cs;

HANDLE hComplete;

TCHAR buf[BUFSIZ];

int nBytes;

//number of per receive

const int nNumPerRecv = BUFSIZ;

<!--[if !supportEmptyParas]--> <!--[endif]-->

//从socket接收数据线程

DWORD WINAPI ReadThread(LPVOID lpParam);

//对接受到的数据进行计算的线程

DWORD WINAPI ComptThread(LPVOID lpParam);

<!--[if !supportEmptyParas]--> <!--[endif]-->

int _tmain(int argc, _TCHAR* argv[])

{

     WSAData wsd;

     int nRet = WSAStartup(0x0202,&wsd);

     if (nRet != 0) {

          cout << "WSAStartup Error = " << WSAGetLastError() << endl;

         return 1;

     }

<!--[if !supportEmptyParas]--> <!--[endif]-->

     SOCKET soRecv = socket(AF_INET,SOCK_STREAM,0);

     SOCKADDR_IN siRecv;

     siRecv.sin_addr.s_addr = inet_addr("127.0.0.1");

     siRecv.sin_family = AF_INET;

     siRecv.sin_port = htons(5150);

<!--[if !supportEmptyParas]--> <!--[endif]-->

     nRet = bind(soRecv,(struct sockaddr*)&siRecv,sizeof(siRecv));

     if (nRet == SOCKET_ERROR) {

         cout << "bind Error = " << WSAGetLastError() << endl;

         return 1;

     }

<!--[if !supportEmptyParas]--> <!--[endif]-->

     listen(soRecv,8);

<!--[if !supportEmptyParas]--> <!--[endif]-->

<!--[if !supportEmptyParas]--> <!--[endif]-->

     HANDLE hThreads[2];

     DWORD dwThread[2];

<!--[if !supportEmptyParas]--> <!--[endif]-->

     //初始化cs

     InitializeCriticalSection(&cs);

<!--[if !supportEmptyParas]--> <!--[endif]-->

     hThreads[0] = CreateThread(NULL,0,ReadThread,(LPVOID)soRecv,0,&dwThread[0]);

     hThreads[1] = CreateThread(NULL,0,ComptThread,NULL,0,&dwThread[1]);

    

     //创建自动重置的event对象,当ReadThread接收数据完毕

     //后将信号置为signaled

     hComplete = CreateEvent(NULL,false,FALSE,"evt");

    

     //等待创建的两个线程结束

     WaitForMultipleObjects(2,hThreads,true,INFINITE);

<!--[if !supportEmptyParas]--> <!--[endif]-->

     //清除cs

     DeleteCriticalSection(&cs);

<!--[if !supportEmptyParas]--> <!--[endif]-->

     return 0;

}

<!--[if !supportEmptyParas]--> <!--[endif]-->

//从socket接收数据线程

DWORD WINAPI ReadThread(LPVOID lpParam){

     int nTotal = 0;

     int nRead = 0;

     int nLeft = 0;

     int nReadBytes = 0;

     int nBytes = 0;

     SOCKET pSoRecv = (SOCKET)lpParam;

     int dwSend;

     SOCKADDR_IN siSend;

     SOCKET soAccept;

<!--[if !supportEmptyParas]--> <!--[endif]-->

<!--[if !supportEmptyParas]--> <!--[endif]-->

     while (1) {

<!--[if !supportEmptyParas]--> <!--[endif]-->

         nTotal = 0;

         nLeft = nNumPerRecv;

<!--[if !supportEmptyParas]--> <!--[endif]-->

         /*   10014错误原因

         *    int dwSend = sizeof(dwSend);

              Error = 10014

         */

         int dwSend = sizeof(siSend);

         soAccept = accept(pSoRecv,(struct sockaddr*)&siSend,&dwSend);

         if (soAccept == SOCKET_ERROR) {

              cout << "accept Error = " << WSAGetLastError() << endl;

              system("pause");

<!--[if !supportEmptyParas]--> <!--[endif]-->

         }

<!--[if !supportEmptyParas]--> <!--[endif]-->

<!--[if !supportEmptyParas]--> <!--[endif]-->

         //接收到的数据为空

         nBytes = 0;

         memset(buf,0,BUFSIZ);

         while (nTotal != nNumPerRecv) {

              //同步操作进入cs

              EnterCriticalSection(&cs);

              /*

               *   Recv data from socket and place data in buf[nBytes]

               */

              //nRead = recv(soAccept,&buf[BUFSIZ - nBytes],nLeft,0);

              nRead = recv(soAccept,&buf[nBytes],nLeft,0);

              if (nRead == -1) {

                   cout << "recv error = " << WSAGetLastError() << endl;

                   ExitThread(1);

              }

              nTotal += nRead;

              nLeft -= nRead;

              nBytes += nRead;

              //离开cs

              LeaveCriticalSection(&cs);

<!--[if !supportEmptyParas]--> <!--[endif]-->

         }

         //激发event

         SetEvent(hComplete);

     }

}

//对接受到的数据进行计算的线程

DWORD WINAPI ComptThread(LPVOID lpParam){

     //等待ReadThread将数据接受完成后再进行计算

     while (1) {

         WaitForSingleObject(hComplete,INFINITE);

<!--[if !supportEmptyParas]--> <!--[endif]-->

         //对全局变量操作进入cs

         EnterCriticalSection(&cs);

         cout << buf << endl;

         nBytes -= nNumPerRecv;

         //离开cs

         LeaveCriticalSection(&cs);

     }

<!--[if !supportEmptyParas]--> <!--[endif]-->

     return 0;

<!--[if !supportEmptyParas]--> <!--[endif]-->

}

<!--[if !supportEmptyParas]--> <!--[endif]-->

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章