iopc源码

  1. #include <WinSock2.h>  
  2. #include <Windows.h>  
  3. #include <vector>  
  4. #include <iostream>  
  5.   
  6. using namespace std;  
  7.   
  8. #pragma comment(lib, "Ws2_32.lib")      // Socket编程需用的动态链接库  
  9. #pragma comment(lib, "Kernel32.lib")    // IOCP需要用到的动态链接库  
  10.   
  11. /** 
  12.  * 结构体名称:PER_IO_DATA 
  13.  * 结构体功能:重叠I/O需要用到的结构体,临时记录IO数据 
  14.  **/  
  15. const int DataBuffSize  = 2 * 1024;  
  16. typedef struct  
  17. {  
  18.     OVERLAPPED overlapped;  
  19.     WSABUF databuff;  
  20.     char buffer[ DataBuffSize ];  
  21.     int BufferLen;  
  22.     int operationType;  
  23. }PER_IO_OPERATEION_DATA, *LPPER_IO_OPERATION_DATA, *LPPER_IO_DATA, PER_IO_DATA;  
  24.   
  25. /** 
  26.  * 结构体名称:PER_HANDLE_DATA 
  27.  * 结构体存储:记录单个套接字的数据,包括了套接字的变量及套接字的对应的客户端的地址。 
  28.  * 结构体作用:当服务器连接上客户端时,信息存储到该结构体中,知道客户端的地址以便于回访。 
  29.  **/  
  30. typedef struct  
  31. {  
  32.     SOCKET socket;  
  33.     SOCKADDR_STORAGE ClientAddr;  
  34. }PER_HANDLE_DATA, *LPPER_HANDLE_DATA;  
  35.   
  36. // 定义全局变量  
  37. const int DefaultPort = 6000;         
  38. vector < PER_HANDLE_DATA* > clientGroup;      // 记录客户端的向量组  
  39.   
  40. HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);  
  41. DWORD WINAPI ServerWorkThread(LPVOID CompletionPortID);  
  42. DWORD WINAPI ServerSendThread(LPVOID IpParam);  
  43.   
  44. // 开始主函数  
  45. int main()  
  46. {  
  47. // 加载socket动态链接库  
  48.     WORD wVersionRequested = MAKEWORD(2, 2); // 请求2.2版本的WinSock库  
  49.     WSADATA wsaData;    // 接收Windows Socket的结构信息  
  50.     DWORD err = WSAStartup(wVersionRequested, &wsaData);  
  51.   
  52.     if (0 != err){  // 检查套接字库是否申请成功  
  53.         cerr << "Request Windows Socket Library Error!\n";  
  54.         system("pause");  
  55.         return -1;  
  56.     }  
  57.     if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){// 检查是否申请了所需版本的套接字库  
  58.         WSACleanup();  
  59.         cerr << "Request Windows Socket Version 2.2 Error!\n";  
  60.         system("pause");  
  61.         return -1;  
  62.     }  
  63.   
  64. // 创建IOCP的内核对象  
  65.     /** 
  66.      * 需要用到的函数的原型: 
  67.      * HANDLE WINAPI CreateIoCompletionPort( 
  68.      *    __in   HANDLE FileHandle,     // 已经打开的文件句柄或者空句柄,一般是客户端的句柄 
  69.      *    __in   HANDLE ExistingCompletionPort, // 已经存在的IOCP句柄 
  70.      *    __in   ULONG_PTR CompletionKey,   // 完成键,包含了指定I/O完成包的指定文件 
  71.      *    __in   DWORD NumberOfConcurrentThreads // 真正并发同时执行最大线程数,一般推介是CPU核心数*2 
  72.      * ); 
  73.      **/  
  74.     HANDLE completionPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0);  
  75.     if (NULL == completionPort){    // 创建IO内核对象失败  
  76.         cerr << "CreateIoCompletionPort failed. Error:" << GetLastError() << endl;  
  77.         system("pause");  
  78.         return -1;  
  79.     }  
  80.   
  81. // 创建IOCP线程--线程里面创建线程池  
  82.   
  83.     // 确定处理器的核心数量  
  84.     SYSTEM_INFO mySysInfo;  
  85.     GetSystemInfo(&mySysInfo);  
  86.   
  87.     // 基于处理器的核心数量创建线程  
  88.     for(DWORD i = 0; i < (mySysInfo.dwNumberOfProcessors * 2); ++i){  
  89.         // 创建服务器工作器线程,并将完成端口传递到该线程  
  90.         HANDLE ThreadHandle = CreateThread(NULL, 0, ServerWorkThread, completionPort, 0, NULL);  
  91.         if(NULL == ThreadHandle){  
  92.             cerr << "Create Thread Handle failed. Error:" << GetLastError() << endl;  
  93.         system("pause");  
  94.             return -1;  
  95.         }  
  96.         CloseHandle(ThreadHandle);  
  97.     }  
  98.   
  99. // 建立流式套接字  
  100.     SOCKET srvSocket = socket(AF_INET, SOCK_STREAM, 0);  
  101.   
  102. // 绑定SOCKET到本机  
  103.     SOCKADDR_IN srvAddr;  
  104.     srvAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);  
  105.     srvAddr.sin_family = AF_INET;  
  106.     srvAddr.sin_port = htons(DefaultPort);  
  107.     int bindResult = bind(srvSocket, (SOCKADDR*)&srvAddr, sizeof(SOCKADDR));  
  108.     if(SOCKET_ERROR == bindResult){  
  109.         cerr << "Bind failed. Error:" << GetLastError() << endl;  
  110.         system("pause");  
  111.         return -1;  
  112.     }  
  113.   
  114. // 将SOCKET设置为监听模式  
  115.     int listenResult = listen(srvSocket, 10);  
  116.     if(SOCKET_ERROR == listenResult){  
  117.         cerr << "Listen failed. Error: " << GetLastError() << endl;  
  118.         system("pause");  
  119.         return -1;  
  120.     }  
  121.       
  122. // 开始处理IO数据  
  123.     cout << "本服务器已准备就绪,正在等待客户端的接入...\n";  
  124.   
  125.     // 创建用于发送数据的线程  
  126.     HANDLE sendThread = CreateThread(NULL, 0, ServerSendThread, 0, 0, NULL);  
  127.   
  128.     while(true){  
  129.         PER_HANDLE_DATA * PerHandleData = NULL;  
  130.         SOCKADDR_IN saRemote;  
  131.         int RemoteLen;  
  132.         SOCKET acceptSocket;  
  133.   
  134.         // 接收连接,并分配完成端,这儿可以用AcceptEx()  
  135.         RemoteLen = sizeof(saRemote);  
  136.         acceptSocket = accept(srvSocket, (SOCKADDR*)&saRemote, &RemoteLen);  
  137.         if(SOCKET_ERROR == acceptSocket){   // 接收客户端失败  
  138.             cerr << "Accept Socket Error: " << GetLastError() << endl;  
  139.             system("pause");  
  140.             return -1;  
  141.         }  
  142.           
  143.         // 创建用来和套接字关联的单句柄数据信息结构  
  144.         PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA));  // 在堆中为这个PerHandleData申请指定大小的内存  
  145.         PerHandleData -> socket = acceptSocket;  
  146.         memcpy (&PerHandleData -> ClientAddr, &saRemote, RemoteLen);  
  147.         clientGroup.push_back(PerHandleData);       // 将单个客户端数据指针放到客户端组中  
  148.   
  149.         // 将接受套接字和完成端口关联  
  150.         CreateIoCompletionPort((HANDLE)(PerHandleData -> socket), completionPort, (DWORD)PerHandleData, 0);  
  151.   
  152.           
  153.         // 开始在接受套接字上处理I/O使用重叠I/O机制  
  154.         // 在新建的套接字上投递一个或多个异步  
  155.         // WSARecv或WSASend请求,这些I/O请求完成后,工作者线程会为I/O请求提供服务      
  156.         // 单I/O操作数据(I/O重叠)  
  157.         LPPER_IO_OPERATION_DATA PerIoData = NULL;  
  158.         PerIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_OPERATEION_DATA));  
  159.         ZeroMemory(&(PerIoData -> overlapped), sizeof(OVERLAPPED));  
  160.         PerIoData->databuff.len = 1024;  
  161.         PerIoData->databuff.buf = PerIoData->buffer;  
  162.         PerIoData->operationType = 0;    // read  
  163.   
  164.         DWORD RecvBytes;  
  165.         DWORD Flags = 0;  
  166.         WSARecv(PerHandleData->socket, &(PerIoData->databuff), 1, &RecvBytes, &Flags, &(PerIoData->overlapped), NULL);  
  167.     }  
  168.   
  169.     system("pause");  
  170.     return 0;  
  171. }  
  172.   
  173. // 开始服务工作线程函数  
  174. DWORD WINAPI ServerWorkThread(LPVOID IpParam)  
  175. {  
  176.     HANDLE CompletionPort = (HANDLE)IpParam;  
  177.     DWORD BytesTransferred;  
  178.     LPOVERLAPPED IpOverlapped;  
  179.     LPPER_HANDLE_DATA PerHandleData = NULL;  
  180.     LPPER_IO_DATA PerIoData = NULL;  
  181.     DWORD RecvBytes;  
  182.     DWORD Flags = 0;  
  183.     BOOL bRet = false;  
  184.   
  185.     while(true){  
  186.         bRet = GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (PULONG_PTR)&PerHandleData, (LPOVERLAPPED*)&IpOverlapped, INFINITE);  
  187.         if(bRet == 0){  
  188.             cerr << "GetQueuedCompletionStatus Error: " << GetLastError() << endl;  
  189.             return -1;  
  190.         }  
  191.         PerIoData = (LPPER_IO_DATA)CONTAINING_RECORD(IpOverlapped, PER_IO_DATA, overlapped);  
  192.           
  193.         // 检查在套接字上是否有错误发生  
  194.         if(0 == BytesTransferred){  
  195.             closesocket(PerHandleData->socket);  
  196.             GlobalFree(PerHandleData);  
  197.             GlobalFree(PerIoData);  
  198.             continue;  
  199.         }  
  200.           
  201.         // 开始数据处理,接收来自客户端的数据  
  202.         WaitForSingleObject(hMutex,INFINITE);  
  203.         cout << "A Client says: " << PerIoData->databuff.buf << endl;  
  204.         ReleaseMutex(hMutex);  
  205.   
  206.         // 为下一个重叠调用建立单I/O操作数据  
  207.         ZeroMemory(&(PerIoData->overlapped), sizeof(OVERLAPPED)); // 清空内存  
  208.         PerIoData->databuff.len = 1024;  
  209.         PerIoData->databuff.buf = PerIoData->buffer;  
  210.         PerIoData->operationType = 0;    // read  
  211.         WSARecv(PerHandleData->socket, &(PerIoData->databuff), 1, &RecvBytes, &Flags, &(PerIoData->overlapped), NULL);  
  212.     }  
  213.   
  214.     return 0;  
  215. }  
  216.   
  217.   
  218. // 发送信息的线程执行函数  
  219. DWORD WINAPI ServerSendThread(LPVOID IpParam)  
  220. {  
  221.     while(1){  
  222.         char talk[200];  
  223.         gets(talk);  
  224.         int len;  
  225.         for (len = 0; talk[len] != '\0'; ++len){  
  226.             // 找出这个字符组的长度  
  227.         }  
  228.         talk[len] = '\n';  
  229.         talk[++len] = '\0';  
  230.         printf("I Say:");  
  231.         cout << talk;  
  232.         WaitForSingleObject(hMutex,INFINITE);  
  233.         for(int i = 0; i < clientGroup.size(); ++i){  
  234.             send(clientGroup[i]->socket, talk, 200, 0);  // 发送信息  
  235.         }  
  236.         ReleaseMutex(hMutex);   
  237.     }  
  238.     return 0;  
  239. }  


  1. // IOCP_TCPIP_Socket_Client.cpp  
  2.   
  3. #include <iostream>  
  4. #include <cstdio>  
  5. #include <string>  
  6. #include <cstring>  
  7. #include <winsock2.h>  
  8. #include <Windows.h>  
  9.   
  10. using namespace std;  
  11.   
  12. #pragma comment(lib, "Ws2_32.lib")      // Socket编程需用的动态链接库  
  13.   
  14. SOCKET sockClient;      // 连接成功后的套接字  
  15. HANDLE bufferMutex;     // 令其能互斥成功正常通信的信号量句柄  
  16. const int DefaultPort = 6000;  
  17.   
  18. int main()  
  19. {  
  20. // 加载socket动态链接库(dll)  
  21.     WORD wVersionRequested;  
  22.     WSADATA wsaData;    // 这结构是用于接收Wjndows Socket的结构信息的  
  23.     wVersionRequested = MAKEWORD( 2, 2 );   // 请求2.2版本的WinSock库  
  24.     int err = WSAStartup( wVersionRequested, &wsaData );  
  25.     if ( err != 0 ) {   // 返回值为零的时候是表示成功申请WSAStartup  
  26.         return -1;  
  27.     }  
  28.     if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { // 检查版本号是否正确  
  29.         WSACleanup( );  
  30.         return -1;   
  31.     }  
  32.       
  33. // 创建socket操作,建立流式套接字,返回套接字号sockClient  
  34.      sockClient = socket(AF_INET, SOCK_STREAM, 0);  
  35.      if(sockClient == INVALID_SOCKET) {   
  36.         printf("Error at socket():%ld\n", WSAGetLastError());   
  37.         WSACleanup();   
  38.         return -1;   
  39.       }   
  40.   
  41. // 将套接字sockClient与远程主机相连  
  42.     // int connect( SOCKET s,  const struct sockaddr* name,  int namelen);  
  43.     // 第一个参数:需要进行连接操作的套接字  
  44.     // 第二个参数:设定所需要连接的地址信息  
  45.     // 第三个参数:地址的长度  
  46.     SOCKADDR_IN addrSrv;  
  47.     addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");      // 本地回路地址是127.0.0.1;   
  48.     addrSrv.sin_family = AF_INET;  
  49.     addrSrv.sin_port = htons(DefaultPort);  
  50.     while(SOCKET_ERROR == connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR))){  
  51.         // 如果还没连接上服务器则要求重连  
  52.         cout << "服务器连接失败,是否重新连接?(Y/N):";  
  53.         char choice;  
  54.         while(cin >> choice && (!((choice != 'Y' && choice == 'N') || (choice == 'Y' && choice != 'N')))){  
  55.             cout << "输入错误,请重新输入:";  
  56.             cin.sync();  
  57.             cin.clear();  
  58.         }  
  59.         if (choice == 'Y'){  
  60.             continue;  
  61.         }  
  62.         else{  
  63.             cout << "退出系统中...";  
  64.             system("pause");  
  65.             return 0;  
  66.         }  
  67.     }  
  68.     cin.sync();  
  69.     cout << "本客户端已准备就绪,用户可直接输入文字向服务器反馈信息。\n";  
  70.   
  71.     send(sockClient, "\nAttention: A Client has enter...\n", 200, 0);  
  72.   
  73.     bufferMutex = CreateSemaphore(NULL, 1, 1, NULL);   
  74.   
  75.     DWORD WINAPI SendMessageThread(LPVOID IpParameter);  
  76.     DWORD WINAPI ReceiveMessageThread(LPVOID IpParameter);  
  77.   
  78.     HANDLE sendThread = CreateThread(NULL, 0, SendMessageThread, NULL, 0, NULL);    
  79.     HANDLE receiveThread = CreateThread(NULL, 0, ReceiveMessageThread, NULL, 0, NULL);    
  80.   
  81.          
  82.     WaitForSingleObject(sendThread, INFINITE);  // 等待线程结束  
  83.     closesocket(sockClient);  
  84.     CloseHandle(sendThread);  
  85.     CloseHandle(receiveThread);  
  86.     CloseHandle(bufferMutex);  
  87.     WSACleanup();   // 终止对套接字库的使用  
  88.   
  89.     printf("End linking...\n");  
  90.     printf("\n");  
  91.     system("pause");  
  92.     return 0;  
  93. }  
  94.   
  95.   
  96. DWORD WINAPI SendMessageThread(LPVOID IpParameter)  
  97. {  
  98.     while(1){  
  99.         string talk;  
  100.         getline(cin, talk);  
  101.         WaitForSingleObject(bufferMutex, INFINITE);     // P(资源未被占用)    
  102.         if("quit" == talk){  
  103.             talk.push_back('\0');  
  104.             send(sockClient, talk.c_str(), 200, 0);  
  105.             break;  
  106.         }  
  107.         else{  
  108.             talk.append("\n");  
  109.         }  
  110.         printf("\nI Say:(\"quit\"to exit):");  
  111.         cout << talk;  
  112.         send(sockClient, talk.c_str(), 200, 0); // 发送信息  
  113.         ReleaseSemaphore(bufferMutex, 1, NULL);     // V(资源占用完毕)   
  114.     }  
  115.     return 0;  
  116. }  
  117.   
  118.   
  119. DWORD WINAPI ReceiveMessageThread(LPVOID IpParameter)  
  120. {  
  121.     while(1){     
  122.         char recvBuf[300];  
  123.         recv(sockClient, recvBuf, 200, 0);  
  124.         WaitForSingleObject(bufferMutex, INFINITE);     // P(资源未被占用)    
  125.   
  126.         printf("%s Says: %s""Server", recvBuf);       // 接收信息  
  127.           
  128.         ReleaseSemaphore(bufferMutex, 1, NULL);     // V(资源占用完毕)   
  129.     }  
  130.     return 0;  
  131. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
0X01FC 是一个十六进制数,它对应的二进制表示是 0000 0001 1111 1100。在 STM32 系列的微控制器中,RCC_APB2RSTR 寄存器的每一位都对应一个特定的外设。通过设置寄存器中的位,可以启用或禁用相应外设的复位功能。 根据这个二进制值,我们可以知道该代码禁用了 RCC_APB2PeriphRSTR 寄存器中对应位置为 1 的外设的复位功能。具体来说,根据 STM32 参考手册的 RCC_APB2PeriphRSTR 寄存器描述,这些位对应的外设如下: - Bit 1 对应外设 AFIO(Alternate Function IO) - Bit 2 对应外设 IOPA(IO Port A) - Bit 3 对应外设 IOPB(IO Port B) - Bit 4 对应外设 IOPC(IO Port C) - Bit 5 对应外设 IOPD(IO Port D) - Bit 6 对应外设 IOPE(IO Port E) - Bit 7 对应外设 IOPF(IO Port F) - Bit 8 对应外设 IOPG(IO Port G) - Bit 9 对应外设 ADC1(Analog to Digital Converter 1) - Bit 10 对应外设 ADC2(Analog to Digital Converter 2) - Bit 11 对应外设 TIM1(Timer 1) - Bit 12 对应外设 SPI1(Serial Peripheral Interface 1) - Bit 13 对应外设 TIM8(Timer 8) - Bit 14 对应外设 USART1(Universal Synchronous/Asynchronous Receiver Transmitter 1) - Bit 15 对应外设 ADC3(Analog to Digital Converter 3) - Bit 16 对应外设 TIM9(Timer 9) - Bit 17 对应外设 TIM10(Timer 10) - Bit 18 对应外设 TIM11(Timer 11) 因此,通过将 RCC_APB2PeriphRSTR 寄存器的值设置为 0X01FC,可以禁用这些外设的复位功能

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值