zoukankan      html  css  js  c++  java
  • 操作系统-进程通信(信号量、匿名管道、命名管道、Socket)

    进程通信(信号量、匿名管道、命名管道、Socket)

    具体的概念就没必要说了,参考以下链接。

    Source Code:

    1. 信号量(生产者消费者问题)

     1 #include <iostream>
     2 #include <Windows.h>
     3 #include <process.h>
     4 #include <vector>
     5 using namespace std;
     6 
     7 #define STD _stdcall  //被调用者负责清栈
     8 int BufferSize;       //缓冲区大小
     9 
    10 CRITICAL_SECTION CR;  //临界区
    11 HANDLE Empty = NULL;  //信号量:空闲缓冲区
    12 HANDLE Full = NULL;   //信号量:满缓冲区
    13 vector<int>Buffer;    //缓冲区
    14 
    15 /*生产者线程*/
    16 DWORD STD Producer(void *lp)
    17 {
    18     while(true)//自旋测试
    19     {
    20         //等待空缓冲区:P(empty)
    21         WaitForSingleObject(Full, INFINITE);//一直等待
    22         //进入缓冲区P(mutex)
    23         EnterCriticalSection(&CR);
    24         //生产数据
    25         int s = rand()%10;
    26         Buffer.push_back(s);
    27         cout << "Producer produces an element : " << s <<endl;
    28         //退出缓冲区V(mutex)
    29         LeaveCriticalSection(&CR);
    30         //增加满缓冲区V(full)
    31         ReleaseSemaphore(Empty, 1, NULL);
    32         //睡一会儿
    33         Sleep(2000);
    34     }
    35 }
    36 
    37 /*消费者线程*/
    38 DWORD STD Consumer(void *lp)
    39 {
    40     while(true)//自旋测试
    41     {
    42         //等待满缓冲区:P(empty)
    43         WaitForSingleObject(Empty, INFINITE);//一直等待
    44         //进入缓冲区P(mutex)
    45         EnterCriticalSection(&CR);
    46         //取出数据
    47         int r = Buffer[Buffer.size()-1];
    48         Buffer.pop_back();
    49         cout << "   Consumer consumes an element : " << r <<endl;
    50         //退出缓冲区V(mutex)
    51         LeaveCriticalSection(&CR);
    52         //增加空缓冲区V(full)
    53         ReleaseSemaphore(Full, 1, NULL);
    54         //睡一会儿
    55         Sleep(2000);
    56     }
    57 }
    58 
    59 int main()
    60 {
    61     cout << "Input the number of BufferSize : "; cin >> BufferSize;
    62     //创建信号量
    63     Empty = CreateSemaphore(NULL, 0, BufferSize, NULL);
    64     Full = CreateSemaphore(NULL, BufferSize, BufferSize,NULL);
    65 
    66     //初始化临界区
    67     InitializeCriticalSection(&CR);
    68 
    69     int pNum, cNum;
    70     cout << "Input the number of Producer(Max:10) : "; cin >> pNum;
    71     cout << "Input the number of Consumer(Max:10) : "; cin >> cNum;
    72 
    73     //创建线程
    74     int i;
    75     HANDLE handle[20];
    76     for(i=0; i<pNum; i++)
    77     {
    78         handle[i] = CreateThread(0, 0, &Producer, 0, 0, 0);
    79     }
    80     for(i=pNum; i<pNum+cNum; i++)
    81     {
    82         handle[i] = CreateThread(0, 0, &Consumer, 0, 0, 0);
    83     }
    84 
    85     //回收线程
    86     WaitForMultipleObjects(pNum+cNum, handle, true, INFINITE);
    87 
    88     //释放线程
    89     for(i=0; i<pNum+cNum; i++)
    90     {
    91         CloseHandle(handle[0]);
    92     }
    93 
    94     //释放缓冲区
    95     DeleteCriticalSection(&CR);
    96     return 0;
    97 }
    View Code

    结果:

    2. 匿名管道(本地父进程与子进程通信)

    原理:

    源码:

     1 /*
     2 *匿名管道:父子进程通信
     3 *date : 2018/12/3
     4 *author : yocichen
     5 *status : Done
     6 */
     7 #include <unistd.h>
     8 #include <stdio.h>
     9 #include <stdlib.h>
    10 #include <string.h>
    11 
    12 int main()
    13 {
    14     //pipe1 p to s, pipe2 s to p
    15     int fd_1[2], fd_2[2];
    16 
    17     if(pipe(fd_1)<0 || pipe(fd_2)<0)//fail to create pipe
    18     {
    19         printf("Fail to create the pipe.
    ");
    20         return -1;
    21     }
    22 
    23     char buf[256];//
    24     const char *temp;
    25 
    26     //child
    27     int fork_result = fork();
    28     if(fork_result == 0)
    29     {
    30         close(fd_1[1]);//close read port
    31         close(fd_2[0]);//close write port
    32 
    33         //read message
    34         read(fd_1[0], buf, sizeof(buf));//read message from father port
    35         printf("
    Child  : receive a message from pipe1: %s
    ", buf);
    36 
    37         //write message
    38         temp = "Hi, my parent, I love you too.";
    39         write(fd_2[1], temp, strlen(temp));//child write message to pipe2
    40     }
    41 
    42     else
    43     {
    44         close(fd_2[1]);
    45         close(fd_1[0]);
    46 
    47         //write message
    48         temp = "My child, I love you.";
    49         write(fd_1[1], temp, strlen(temp));//parent write message to pipe1
    50 
    51         //read message
    52         read(fd_2[0], buf, sizeof(buf));//read message from pipe2
    53         printf("
    Parent : receive a message from pipe2: %s
    ", buf);
    54     }
    55     return 0;
    56 }
    View Code

    (注意:该匿名管道程序为Linux系统开发,注意运行环境,windows下使用CodeBlocks可以运行)

    3.命名管道

    原理:

    源码:

     1 #include <windows.h>
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 
     5 int main()
     6 {
     7     //创建命名管道
     8     HANDLE namedPipe = CreateNamedPipeA("\\.\pipe\testName", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, NULL);
     9 
    10     //校验状态
    11     if(namedPipe == INVALID_HANDLE_VALUE)
    12     {
    13         printf("Server: Fail to create named pipe.
    ");
    14     }
    15     else
    16     {
    17         printf("Server: Succeed to create pipe.
    ");
    18     }
    19 
    20     OVERLAPPED op;
    21     ZeroMemory(&op, sizeof(OVERLAPPED));
    22 
    23     //创建事件对象
    24     op.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    25 
    26     //等待连接
    27     bool b = ConnectNamedPipe(namedPipe, &op);
    28     printf("Server: Listen...
    ");
    29 
    30     int status = WaitForSingleObject(op.hEvent, INFINITE);
    31     //连接成功
    32     if(status == 0)
    33     {
    34         printf("Server: Succeed to connect.
    ");
    35     }
    36     else
    37     {
    38         printf("Server: Fail to connect.
    ");
    39     }
    40 
    41     //通信
    42     char buf[100] = "来玩个猜数游戏吧!
    ";
    43     DWORD wp;
    44     WriteFile(namedPipe, buf, strlen(buf), &wp, NULL);
    45 
    46     int ans = rand()%9+1;
    47     while(status == 0)
    48     {
    49         ZeroMemory(buf, 100);
    50         ReadFile(namedPipe, buf, 100, &wp, NULL);
    51         printf("收到:%s
    ", buf);
    52 
    53         if(int(buf[0] - '0') < ans)
    54         {
    55             WriteFile(namedPipe, "小了,再猜一次!
    ", strlen("小了,再猜一次!
    "), &wp, NULL);
    56         }
    57         else if((buf[0]-'0') > ans)
    58         {
    59             WriteFile(namedPipe, "大了,再猜一次!
    ", strlen("大了,再猜一次!
    "), &wp, NULL);
    60         }
    61         else
    62         {
    63             WriteFile(namedPipe, "猜对了!
    ", strlen("小了,再猜一次!
    "), &wp, NULL);
    64             break;
    65         }
    66 
    67         if(buf[0] == '0')
    68         {
    69             printf("客户已退出!
    ");
    70             break;
    71         }
    72     }
    73 
    74     //通信结束
    75     DisconnectNamedPipe(namedPipe);
    76     return 0;
    77 }
    Server
     1 #include <windows.h>
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 
     5 int main()
     6 {
     7     //检查管道是否存在
     8     bool b = WaitNamedPipeA("\\.\pipe\testName", 0);
     9 
    10     //打开管道
    11     HANDLE hFile = CreateFileA("\\.\pipe\testName", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    12 
    13     //是否连接成功
    14     if(b ==0 || hFile == INVALID_HANDLE_VALUE)
    15     {
    16         printf("Client: fail to connect.
    ");
    17         return 0;
    18     }
    19     else
    20     {
    21         printf("Client: Succeed to connect.
    ");
    22     }
    23 
    24     //通信
    25     char buf[100];
    26     ZeroMemory(buf, 100);
    27     DWORD rp;
    28     ReadFile(hFile, buf, 100, &rp, NULL);//读取
    29     printf(buf);
    30 
    31     while(true)
    32     {
    33         printf("输入数字:");
    34         scanf("%s", buf);
    35         WriteFile(hFile, buf, strlen(buf), &rp, NULL);
    36 
    37         while(ReadFile(hFile, buf, 100, &rp, NULL) == true)
    38         {
    39             printf("Server: ");
    40             printf(buf);
    41             break;
    42         }
    43     }
    44 
    45     CloseHandle(hFile);
    46     return 0;
    47 }
    Client

    4.Socket网络进程通信

    原理:

    源码:

     1 /*注意头文件顺序*/
     2 #include <winsock2.h>
     3 #include <stdio.h>
     4 #include <stdlib.h>
     5 #pragma comment(lib, "ws2_32.lib")      //引入动态链接库
     6 
     7 int main()
     8 {
     9     WORD ws_version = MAKEWORD(2, 2);   //指定Winsock version
    10     WSADATA wsaData;                    //WSA 函数的参数
    11 
    12     /*初始化winsock*/
    13     WSAStartup(ws_version, &wsaData);
    14 
    15     /*socket*/
    16     SOCKET s_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    17 
    18     SOCKADDR_IN addr_server;
    19     addr_server.sin_family = AF_INET;   //协议
    20     addr_server.sin_port = htons(5050); //端口
    21     addr_server.sin_addr.s_addr = htonl(INADDR_ANY);    //IP:任意IP
    22 
    23     /*bind*/
    24     int bind_status;
    25     bind_status = bind(s_server, (SOCKADDR*)&addr_server, sizeof(SOCKADDR));
    26     if(bind_status == SOCKET_ERROR)
    27     {
    28         printf("bind error : fail to bind! 
    "); 
    29     }
    30     else
    31     {
    32         printf("bind successfully!
    ");
    33     }
    34 
    35     /*listen*/
    36     listen(s_server, 5);//max=5
    37     printf("listening ... 
    ");
    38 
    39     SOCKADDR_IN addr_client;            //存储client地址信息
    40     int len = sizeof(SOCKADDR);
    41     int count = 0;                        //统计客户数目
    42     SOCKET s_client;                    //连接的socket
    43 
    44     char buf[1000];
    45     while(true)
    46     {
    47         printf("等待客户端连接...
    ");
    48         /*accept*/
    49         s_client = accept(s_server, (SOCKADDR*)&addr_client, &len);
    50         if(s_client == INVALID_SOCKET)
    51         {
    52             printf("Accept error : fail to accept client! ");
    53         }
    54         else//连接成功
    55         {
    56             count++;
    57             printf("
    Accept successfully!
    ");
    58             
    59             printf("---------------------------------------------
    ");
    60             printf(" 编号:%d 
    ", count);
    61             printf(" Port:%d
    ", ntohs(addr_client.sin_port));
    62             printf(" IP:%s
    ", inet_ntoa(addr_client.sin_addr));//inet_ntoa(SOCKADDR.in_addr)网络地址转换为IP
    63             
    64             int recv_status = recv(s_client, buf, 100, 0);
    65             if(recv_status > 0)
    66             {
    67                 printf("收到:");
    68                 buf[recv_status] = 0x00;//截断
    69                 printf(buf);
    70                 printf("
    ---------------------------------------------
    ");
    71             }
    72             const char *sendData = "你好!客户端!我是服务器";
    73             send(s_client, sendData, strlen(sendData), 0);
    74             closesocket(s_client);
    75         }
    76     }
    77 
    78     closesocket(s_server);      //关闭socket
    79     WSACleanup();
    80 
    81     return 0;
    82 }
    Server
     1 #include <winsock2.h>
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <windows.h>
     5 #include <iostream>
     6 #pragma comment(lib, "ws2_32.lib")      //引入动态链接库
     7 #define SERVER_IP "192.168.31.102"        //客户端IP
     8 using namespace std;
     9 
    10 int main()
    11 {
    12     WORD ws_version = MAKEWORD(2, 2);   //指定Winsock version
    13     WSADATA wsaData;                    //WSA 函数的参数
    14 
    15     /*初始化winsock*/
    16     WSAStartup(ws_version, &wsaData);
    17 
    18     while(true)
    19     {
    20         /*socket*/
    21         SOCKET s_client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    22 
    23         SOCKADDR_IN addr_server;
    24         addr_server.sin_family = AF_INET;   //协议
    25         addr_server.sin_port = htons(5050); //端口
    26         addr_server.sin_addr.s_addr = inet_addr(SERVER_IP);
    27 
    28         char buf[100];
    29         int send_status, recv_status;
    30 
    31         /*Connect*/
    32         int cnct_status = connect(s_client, (SOCKADDR*)&addr_server, sizeof(SOCKADDR));
    33         if(cnct_status == 0)//连接成功
    34         {
    35                 printf("
    Connecting... done
    ");
    36 
    37                 //向服务端发送消息
    38                 printf("输入发送信息:");
    39                 scanf("%s", buf);
    40                 send_status = send(s_client, buf, 10, 0);
    41                 if(send_status == SOCKET_ERROR)//发送失败
    42                 {
    43                     printf("send error!
    ");
    44                 }
    45                 else
    46                 {
    47                     printf("发送:%s
    ", buf);
    48                     //接受服务端消息
    49                     recv_status = recv(s_client, buf, 100, 0);
    50                     buf[recv_status] = 0x00;//截断
    51                     printf("收到:%s
    ", buf);
    52                 }
    53         }
    54         else
    55         {
    56             printf("Test:fail to connect server! 
    ");
    57         }
    58         closesocket(s_client);
    59     }
    60 
    61     WSACleanup();
    62 
    63     return 0;
    64 }
    Client

  • 相关阅读:
    省市级联
    innerText与innerHTML的区别
    使用代码提交表单
    Date的使用
    Array(数组)的使用
    [贪心]Rest Stops
    [数论][Miller_Rabin] Goldbach
    [简单思维题]Hoofball
    [数论][容斥原理]Co-prime
    [图论][二分图最大匹配]Courses
  • 原文地址:https://www.cnblogs.com/yocichen/p/10075324.html
Copyright © 2011-2022 走看看