锁定模式下的非锁定实现

原创 2006年06月07日 22:38:00

锁定模式下的非锁定实现

Lanno Ckeeke  2006060701

说明

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

     对数据的处理可以是耗时操作,它不会对数据的接收带来影响。

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

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

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

本代码中应用CriticalSectionevent来实现。

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

完整代码及注释

  1. // zBlogSocket.cpp : 定义控制台应用程序的入口点。
  2. //
  3. //多线程socket锁定
  4.  
  5. #include "stdafx.h"
  6. #include <WinSock2.h>
  7. #include <Windows.h>
  8. #include <iostream>
  9. using namespace std;
  10.  
  11. CRITICAL_SECTION cs;
  12. HANDLE hComplete;
  13. TCHAR buf[BUFSIZ];
  14. int nBytes;
  15. //number of per receive
  16. const int nNumPerRecv = BUFSIZ;
  17.  
  18. //从socket接收数据线程
  19. DWORD WINAPI ReadThread(LPVOID lpParam);
  20. //对接受到的数据进行计算的线程
  21. DWORD WINAPI ComptThread(LPVOID lpParam);
  22.  
  23. int _tmain(int argc, _TCHAR* argv[])
  24. {
  25.      WSAData wsd;
  26.      int nRet = WSAStartup(0x0202,&wsd);
  27.      if (nRet != 0) {
  28.           cout << "WSAStartup Error = " << WSAGetLastError() << endl;
  29.          return 1;
  30.      }
  31.  
  32.      SOCKET soRecv = socket(AF_INET,SOCK_STREAM,0);
  33.      SOCKADDR_IN siRecv;
  34.      siRecv.sin_addr.s_addr = inet_addr("127.0.0.1");
  35.      siRecv.sin_family = AF_INET;
  36.      siRecv.sin_port = htons(5150);
  37.  
  38.      nRet = bind(soRecv,(struct sockaddr*)&siRecv,sizeof(siRecv));
  39.      if (nRet == SOCKET_ERROR) {
  40.          cout << "bind Error = " << WSAGetLastError() << endl;
  41.          return 1;
  42.      }
  43.  
  44.      listen(soRecv,8);
  45.  
  46.  
  47.      HANDLE hThreads[2];
  48.      DWORD dwThread[2];
  49.  
  50.      //初始化cs
  51.      InitializeCriticalSection(&cs);
  52.  
  53.      hThreads[0] = CreateThread(NULL,0,ReadThread,(LPVOID)soRecv,0,&dwThread[0]);
  54.      hThreads[1] = CreateThread(NULL,0,ComptThread,NULL,0,&dwThread[1]);
  55.     
  56.      //创建自动重置的event对象,当ReadThread接收数据完毕
  57.      //后将信号置为signaled
  58.      hComplete = CreateEvent(NULL,false,FALSE,"evt");
  59.     
  60.      //等待创建的两个线程结束
  61.      WaitForMultipleObjects(2,hThreads,true,INFINITE);
  62.  
  63.      //清除cs
  64.      DeleteCriticalSection(&cs);
  65.  
  66.      return 0;
  67. }
  68.  
  69. //从socket接收数据线程
  70. DWORD WINAPI ReadThread(LPVOID lpParam){
  71.      int nTotal = 0;
  72.      int nRead = 0;
  73.      int nLeft = 0;
  74.      int nReadBytes = 0;
  75.      int nBytes = 0;
  76.      SOCKET pSoRecv = (SOCKET)lpParam;
  77.      int dwSend;
  78.      SOCKADDR_IN siSend;
  79.      SOCKET soAccept;
  80.  
  81.  
  82.      while (1) {
  83.  
  84.          nTotal = 0;
  85.          nLeft = nNumPerRecv;
  86.  
  87.          /*   10014错误原因
  88.          *    int dwSend = sizeof(dwSend);
  89.               Error = 10014
  90.          */
  91.          int dwSend = sizeof(siSend);
  92.          soAccept = accept(pSoRecv,(struct sockaddr*)&siSend,&dwSend);
  93.          if (soAccept == SOCKET_ERROR) {
  94.               cout << "accept Error = " << WSAGetLastError() << endl;
  95.               system("pause");
  96.  
  97.          }
  98.  
  99.  
  100.          //接收到的数据为空
  101.          nBytes = 0;
  102.          memset(buf,0,BUFSIZ);
  103.          while (nTotal != nNumPerRecv) {
  104.               //同步操作进入cs
  105.               EnterCriticalSection(&cs);
  106.               /*
  107.                *   Recv data from socket and place data in buf[nBytes]
  108.                */
  109.               //nRead = recv(soAccept,&buf[BUFSIZ - nBytes],nLeft,0);
  110.               nRead = recv(soAccept,&buf[nBytes],nLeft,0);
  111.               if (nRead == -1) {
  112.                    cout << "recv error = " << WSAGetLastError() << endl;
  113.                    ExitThread(1);
  114.               }
  115.               nTotal += nRead;
  116.               nLeft -= nRead;
  117.               nBytes += nRead;
  118.               //离开cs
  119.               LeaveCriticalSection(&cs);
  120.  
  121.          }
  122.          //激发event
  123.          SetEvent(hComplete);
  124.      }
  125. }
  126. //对接受到的数据进行计算的线程
  127. DWORD WINAPI ComptThread(LPVOID lpParam){
  128.      //等待ReadThread将数据接受完成后再进行计算
  129.      while (1) {
  130.          WaitForSingleObject(hComplete,INFINITE);
  131.  
  132.          //对全局变量操作进入cs
  133.          EnterCriticalSection(&cs);
  134.          cout << buf << endl;
  135.          nBytes -= nNumPerRecv;
  136.          //离开cs
  137.          LeaveCriticalSection(&cs);
  138.      }
  139.  
  140.      return 0;
  141.  
  142. }

 

MySQL InnoDB的一致性非锁定读

MySQL InnoDB存储引擎的一致性非锁定读
  • JayLoveU
  • JayLoveU
  • 2017年05月15日 10:41
  • 238

做一个合格的程序猿之MYSQL存储引擎INNODB简介之非锁定读(二)

MYSQL5.5版本之后默认的存储引擎是INNODB,其最主要的特点是支持行级锁,支持事务,支持非锁定读   面试中最常见的问题是mysql的事务隔离级别   好了,背诵完了之后...
  • linuu
  • linuu
  • 2016年03月03日 20:02
  • 699

Subversion使用“锁定-编辑-解锁”模型

Subversion使用与CVS相似的工作模型,也就是“拷贝-修改-合并”,但是有时候还是很有必要使用“锁定-编辑-解锁”模型,例如对于二进制文件,或者其他不太适合合并的文件。 属性在《使用Subve...
  • henren555
  • henren555
  • 2014年12月05日 17:38
  • 1014

VMWare虚拟机提示:锁定文件失败,打不开磁盘的解决办法

如果使用VMWare虚拟机的时候突然系统崩溃蓝屏,有一定几率会导致无法启动,会提示:“锁定文件失败,打不开磁盘...或它所依赖的某个快照磁盘,开启模块DiskEarly的操作失败,未能启动虚拟机”,这...
  • asdfzjs
  • asdfzjs
  • 2015年09月15日 11:48
  • 14963

如何在quartus下做逻辑锁定(quartus,逻辑锁定)

摘要:   当你的设计做得越来越大,性能要求越来越高的时候,你就会发现,之前跑得好好的模块,怎么突然间不行了,其实这就是约束的问题,FPGA内部的布局布线就像我们画PCB时的自动布线,如果没有规...
  • USB_ABC
  • USB_ABC
  • 2017年05月27日 12:04
  • 381

一致性非锁定读与一致性锁定读

背景 innodb存储引擎实现了两种标准的行级锁:S锁和X锁,S锁被称为共享锁,允许事务读一行数据,X锁被称为排它锁,允许事务删除或更新一行数据。 一致性非锁定读指...
  • jek123456
  • jek123456
  • 2016年12月19日 09:20
  • 135

css实现table锁定表头

在做项目中,碰到表格数据全部加载,不要分页,就需要锁定表头的业务。自己也上网搜了一些资料, 1.css+html实现 一般的思路就是两个table拼接,不过问题是上下表单可...
  • muyi8805
  • muyi8805
  • 2015年07月13日 22:13
  • 1556

SQLSERVER sa 账号被锁定

修改公司云服务器 SQLSERVER 密码时,不小心打上那个强制实施密码策略,然后就扑街了; 说 sa 账号被锁定;更加扑街的是 本机的管理员账号 没有加到 登录名 里面,使用 本机账号也登陆不了;...
  • hesi726
  • hesi726
  • 2016年11月08日 11:19
  • 1402

extjs_06_grid(列锁定&列分组)

extjs_06_grid(列锁定&列分组)
  • adam_zs
  • adam_zs
  • 2014年06月25日 22:06
  • 1939

解除表锁定的——sql语句方案

你曾遇到过 delete from A  没反应吗?明明感觉sql语句写对了,为啥删除不了呢?是程序代码问题?还是sql问题? 然后把sql语句搬到客户端中,比如PLSQL中,咋也没有反应? 若P...
  • llhhyy1989
  • llhhyy1989
  • 2013年11月25日 20:18
  • 2395
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:锁定模式下的非锁定实现
举报原因:
原因补充:

(最多只允许输入30个字)