安全传输平台项目——统一通信组件-统一共享内存组件

在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

10-安全传输平台项目-第04天(统一通信组件-统一共享内存组件)

 

一、复习

1、wind下制作动态库
2、linux下制作动态库
3、makefile复习
4、统一通信组件—socket通信
5、统一通信组件-服务器端实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
 
#include "poolsocket.h"    
 
 void *start_routine(void * arg)
 {
     int ret;
     int timeout = 3;
     int connfd = (int)arg;
     
     unsigned char *out = NULL;
     int outlen = 0;
     
     while (1) {

        //服务器端端接受报文
        ret = sckServer_rev(connfd, timeout, &out, &outlen); 
        if (ret == Sck_ErrPeerClosed) {
            // 检测到 对端关闭,关闭本端。
            printf("----------------ErrPeerClosed 关闭服务器\n");
            break;
        } else if (ret == Sck_ErrTimeOut) {
            printf("---服务器检测到客户端发送数据 超时 \n");
            continue;
        } else if (ret != 0) {
            printf("未知错误\n");
            break;
        }
    
        // 处理数据。 ----- 回射
        printf("====客户端发送了:%s\n", out);
    
         //服务器端发送报文
        ret = sckServer_send(connfd, timeout, out, outlen);
         if (ret == Sck_ErrPeerClosed) {
            // 检测到 对端关闭,关闭本端。
            printf("---ErrPeerClosed \n");
            break;
        } else if (ret == Sck_ErrTimeOut) {
            printf("---服务器检测到本端发送数据 超时 \n");
            continue;
        } else if (ret != 0) {
            printf("未知错误\n");
            break;
        }
    }
    sckServer_close(connfd);
     return NULL;
 }

int main(void)
{
    int listenfd;
    int port = 8080;
    int ret = 0;
    
    int timeout = 3;
    int connfd = -1;
    
    pthread_t pid;
    
    //服务器端初始化
    ret = sckServer_init(port, &listenfd);
    if (ret != 0) {
        printf("sckServer_init error %d\n", ret);    
        return ret;
    }
    
    while (1) {
        ret = sckServer_accept(listenfd, timeout, &connfd);
        if (ret == Sck_ErrTimeOut){
            printf("-----客户端连接超时----\n");
            continue;    
        } else if(ret != 0)  {
            printf("sckServer_accept error %d\n", ret);    
            return ret;
        }
        ret = pthread_create(&pid, NULL, start_routine, (void *)connfd);                    
    }
     
     //服务器端环境释放 
    sckServer_destroy();

    return 0;    
}
server.c

 

二、安全传输平台项目—统一通信组件

1、客户端连接服务器

》编写client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
 
#include "poolsocket.h"  

int main(void)
{
    char *ip = "127.0.0.1"; 
    int port = 8080;
    int time = 3; 
    int connfd = -1;
    int ret = -1;
    
    unsigned char *data = "abcdefg";
    int datalen = 5;
    
    unsigned char *out = NULL;
    int outlen = -1;
    
    //客户端 初始化
    ret = sckClient_init();
    if (ret != 0) {
        printf("sckClient_init error %d\n", ret);    
        return ret;
    }
    
    while (1) {
    
        //客户端 连接服务器
        ret = sckClient_connect(ip, port, time, &connfd);
         if (ret == Sck_ErrTimeOut) {
            printf("---客户端连接服务器 超时 \n");
            continue;
        } else if (ret != 0) {
            printf("客户端连接服务器 失败: errorNO:%d\n", ret);
            break;
        }
            
        //客户端 发送报文
        ret = sckClient_send(connfd, time, data, datalen);
        if (ret == Sck_ErrPeerClosed) {
            printf("---服务器关闭,客户端断开连接 \n");
            break;
        } else if (ret == Sck_ErrTimeOut) {
            printf("---服务器接收数据 超时 \n");
            continue;
        } else if (ret != 0) {
            printf("客户端发送数据失败:errorNO:%d\n", ret);
            break;
        }
        sleep(1);

        //客户端 接受报文
        ret = sckClient_rev(connfd, time, &out, &outlen); 
        if (ret == Sck_ErrPeerClosed) {
            printf("---服务器关闭,客户端断开连接 \n");
            break;
        } else if (ret == Sck_ErrTimeOut) {
            printf("---服务器发送数据 超时 \n");
            continue;
        } else if (ret != 0) {
            printf("客户端接收数据失败:errorNO:%d\n", ret);
            break;
        }    
    }

    //客户端 关闭和服务端的连接
    if (connfd != -1)
        sckClient_closeconn(connfd);
        
    //客户端 释放
    sckClient_destroy();
    
    return 0;    
}
client.c

创建目录test,把makefile、libitcastsocket.so、poolsocket.h放入test目录下。

>make

>./server

打开另一个终端,切换到test目录下,执行>./client,然后查看原终端的数据接收情况。

注意中文乱码,需要转换:

为什么会出现服务器检测到客户端发送数据超时?

 

2、客户端连接池连接服务器

》编写client2.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
 
#include "poolsocket.h" 

/*
typedef struct _SCKClitPoolParam
{
    char     serverip[64];
    int     serverport;
    int     bounds; //池容量
    int     connecttime;
    int     sendtime;
    int     revtime;
}SCKClitPoolParam;
*/ 

void *mystart_routin(void *arg) 
{
    int ret = 0;
    int connfd = -1;
    void *handle = arg;
    
    unsigned char *data = "abcdefg";
    int datalen = 5;
    
    unsigned char *out = NULL;
    int outlen = -1;
        
    // 获取一条连接池中的链接:
    ret = sckCltPool_getConnet(handle, &connfd);
    if (ret != 0) {
        printf("从连接池 获取 连接失败:%d\n", ret);
        return NULL;    
    }
    //可以增加发送数据的次数,flag=10,flag--
    while (1) {
        ret = sckCltPool_send(handle, connfd, data, datalen);
        if (ret == Sck_ErrPeerClosed) {
            printf("---服务器关闭,客户端断开连接 \n");
            break;
        } else if (ret == Sck_ErrTimeOut) {
            printf("---服务器接收数据 超时 \n");
            continue;
        } else if (ret != 0) {
            printf("客户端发送数据失败:errorNO:%d\n", ret);
            break;
        }
        
        ret = sckCltPool_rev(handle, connfd, &out, &outlen); 
        if (ret == Sck_ErrPeerClosed) {
            printf("---服务器关闭,客户端断开连接 \n");
            break;
        } else if (ret == Sck_ErrTimeOut) {
            printf("---服务器发送数据 超时 \n");
            continue;
        } else if (ret != 0) {
            printf("客户端接收数据失败:errorNO:%d\n", ret);
            break;
        }
        printf("------接收到 服务器回发数据:%s\n", out);        
    }
    sckCltPool_putConnet(handle, connfd, 0); 

    
    return NULL;
}


int main(void)
{
    int i = 0;
    int ret = 0;
    pthread_t pidArray[6] = {0};
    
    SCKClitPoolParam clientPoolparam;
    strcpy(clientPoolparam.serverip, "127.0.0.1");
    clientPoolparam.serverport = 8080;
    clientPoolparam.bounds = 10;
    clientPoolparam.connecttime = 3;
    clientPoolparam.sendtime = 3;
    clientPoolparam.revtime = 3;
    
    void *handle = NULL;

    //客户端 初始化
    ret = sckCltPool_init(&handle, &clientPoolparam);
    if (ret != 0) {
        printf("sckCltPool_init error %d\n", ret);    
        return ret;
    }
    
    while (1) {
        
        for (i = 0; i < 6; i++) {
            pthread_create(&pidArray[i], NULL, mystart_routin, handle);    //需要判断返回值
        }
        
        for (i = 0; i< 6; i++) {
            pthread_join(pidArray[i], NULL);    
        }
    }

    //销毁连接池
    sckCltPool_destroy(handle);

    return 0;    
}
client2.c

>make

>./server

打开另一个终端,切换到test目录下,执行>./client,然后查看原终端的数据接收情况。

 

3、线程传参现象展示

>vi a_server.c

#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>


#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include "poolsocket.h"


void *mystart_routine(void *arg)
{
    int         ret = 0;
    int         timeout = 3;
    int         connfd = (int)arg;
    
    unsigned char     *out = NULL;
    int             outlen = 0;
    
    while (1)
    {    
        //服务器端端接受报文
        ret =  sckServer_rev(connfd, timeout, &out, &outlen); //1
        if (ret == Sck_ErrPeerClosed)
        {
            //printf("aaaaa \n");
            printf("服务器端检测到客户端有一条连接已关闭 \n");
            break;
        }
        else if (ret == Sck_ErrTimeOut)
        {
            printf("服务器端send超时\n");
            continue;
        }
        else if (ret != 0)
        {
            printf("服务器端 sckServer_send() err\n");
            break;
        }
    
        printf("out:%s \n", out);  //回射
        
        //服务器端发送报文
        ret =  sckServer_send(connfd, timeout, out, outlen);
        if (ret == Sck_ErrPeerClosed)
        {
            sck_FreeMem((void **)&out);
            printf("服务器端检测到客户端有一条连接已关闭\n");
            break;
        }
        else if (ret == Sck_ErrTimeOut)
        {
            sck_FreeMem((void **)&out);
            printf("服务器端send超时\n");
            continue;
        }
        else if (ret != 0)
        {
            sck_FreeMem((void **)&out);
            printf("服务器端 sckServer_send() err\n");
            break;
        }
        sck_FreeMem((void **)&out);
    }
    
    sckServer_close(connfd);
    return NULL;
}


int main()
{
    int         ret         = 0;
    int             port         = 8001;
    int         listenfd     = 0;
    int         timeout        = 3;
    int         connfd = 0;
    pthread_t     pid;
    
    
    //函数声明
    //服务器端初始化
    ret = sckServer_init(port, &listenfd);
    if (ret != 0)
    {
        printf("func sckServer_init() err:%d \n", ret);
        return ret;
    }
    
    while (1)
    {
        ret = sckServer_accept(listenfd, timeout, &connfd);
        if (ret == Sck_ErrTimeOut)
        {
            printf("func sckServer_accept() Sck_ErrTimeOut\n");
            continue;
        }
        else if (ret != 0)
        {
            ret = 2;
            printf("fun sckServer_accept() err :%d \n", ret);
            break;
        }
    
        pthread_create(&pid, NULL,  mystart_routine, (void *)(connfd));

    }


    //服务器端环境释放 
    int sckServer_destroy();
    printf("hello....\n");    
}
a_server.c

>vi a_client3err.c

#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include "poolsocket.h"

typedef struct _ThreadInfo
{
    void     *handle;
    int     iLoop;
    int     iArrayIndex;   //线程数组的下标
}ThreadInfo;


void* myclient_startroutine (void *arg)
{
     int             i = 0, ret = 0;
     int             connfd = 0;
 
    char             data[64] = {0};
     int             datalen = 0;
     
    unsigned char  *out = NULL;
    int             outlen = 0;
    
    ThreadInfo         *pThreadInfo = (ThreadInfo *)arg;
    void             *handle = pThreadInfo->handle; //

    
    //客户端 socket池 获取一条连接 
    ret = sckCltPool_getConnet(handle, &connfd);
    if (ret != 0)
    {
        printf("func sckCltPool_getConnet() err:%d\n", ret);
        return NULL;
    }
    
    for (i=0; i<pThreadInfo->iLoop; i++)
    {
        //客户端 socket池 发送数据 
        memset(data, 0, sizeof(data));
        sprintf(data, "第%d线程, 第%d圈", pThreadInfo->iArrayIndex, i+1);
        
        ret = sckCltPool_send(handle, connfd,  data, strlen(data));
        if (ret == Sck_ErrPeerClosed)
         { 
             printf("sckCltPool_send 客户端检测到 服务器已经关闭 退出\n");
             break;    
         }
         else if (ret == Sck_ErrTimeOut)
         {
             printf(" sckCltPool_send timeout \n");
             break;
         }
         else if (ret != 0)
         {
             printf("fun sckServer_rev() err:%d \n", ret);
             break;
         }

        //客户端 socket池 接受数据
        ret =  sckCltPool_rev(handle, connfd, &out, &outlen); //1
        if (ret == Sck_ErrPeerClosed)
         { 
             printf("sckCltPool_rev 客户端检测到 服务器已经关闭 退出\n");
             break;    
         }
         else if (ret == Sck_ErrTimeOut)
         {
             printf(" sckCltPool_rev timeout \n");
             break;
         }
         else if (ret != 0)
         {
             printf("fun sckCltPool_rev() err:%d \n", ret);
             break;
         }
         printf("客户端 out:%s \n", out);
         sck_FreeMem((void **)&out);
    }
    
    //客户端 socket池 把连接放回 socket池中 
    sckCltPool_putConnet(handle, connfd, 0); //0正常 1
    
     return NULL;
}
 
int main(void)
{
    int         ret = 0, i = 0;
    char         *ip = "127.0.0.1"; 
    int         port = 8001;
    int         time = 3;
    int         connfd = 0;
    
    int            iLoop = 0; //圈数
    int            iThreadNum = 0 ; //线程数
    
    void         *handle = NULL;
    pthread_t     pidArray[1024]; 
    
    ThreadInfo             threadInfo;
    memset(&threadInfo, 0, sizeof(ThreadInfo));
    
    SCKClitPoolParam            sckClitPoolParm;
    memset(&sckClitPoolParm, 0, sizeof(SCKClitPoolParam));
    strcpy(sckClitPoolParm.serverip,  "127.0.0.1");
    sckClitPoolParm.serverport = 8001;
    sckClitPoolParm.bounds = 10;
    sckClitPoolParm.connecttime = 3;
    sckClitPoolParm.sendtime = 3;
    sckClitPoolParm.revtime = 3;
    
    
    printf("\n请输入线程的个数: ");
    scanf("%d", &iThreadNum);
    
    printf("\n请输入每个线程运行圈数: ");
    scanf("%d", &iLoop);
    
    if (iThreadNum >= 1024)
    {
        printf("iThreadNum大于1024\n");
        return 0;
    }

    //客户端 socket池初始化
    ret = sckCltPool_init(&handle,  &sckClitPoolParm);
    if (ret != 0)
    {
        printf("func  sckCltPool_init() err:%d \n ", ret);
        return ret;
    }
    
    //启动多线程 
    for (i=0; i<iThreadNum; i++)
    {
        threadInfo.handle = handle;              //alt + 鼠标键左键拖动 
        threadInfo.iLoop =  iLoop;
        threadInfo.iArrayIndex = i + 1;
    pthread_create(&pidArray[i], NULL, myclient_startroutine, (void *)&threadInfo);
    }
    
    
    //主进程 等待子线程 结束
    for (i=0; i<iThreadNum; i++)
    {
         pthread_join(pidArray[i], NULL);
    }
    
    
    //客户端 socket池 销毁连接
    sckCltPool_destroy(handle);

    printf("client hello....\n");
    
    
    return 0;
}
a_client3err.c

>make

>./a_server

打开另一个终端,切换到test目录下,执行>./a_client3err,然后查看原终端的数据接收情况。

1)问题:pthread_create(&pidArray[i], NULL, myclient_startroutine, (void *)&threadInfo);中的最后一个参数需要加地址符号吗?

由于threadInfo是一个结构体,从大小及值拷贝需要的空间复杂度考虑,所以必须传入地址,不能传值。结论——结构体做参数,最好传地址!!!

2)问题:每次都是最后一个线程跑圈?

分析:pthread_create传参最后一个参数threadInfo使用了地址传参。需要看4、线程传参内存冗余法

 

4、线程传参内存冗余法

》内存冗余分析图:

注意:形参和局部变量地位等同,都位于栈上。

原因:线程子函数栈空间调用了main函数栈空间的值,当线程几乎同时创建时,去读取main栈空间的值时,main栈空间的值i还在变化(自增)。所以需要为每个线程子函数创建属于自己的栈空间。

>vi a_client4.c

#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include "poolsocket.h"

typedef struct _ThreadInfo
{
    void     *handle;
    int     iLoop;
    int     iArrayIndex;//线程数组的下标
}ThreadInfo;


 void* myclient_startroutine (void *arg)
 {
     int             i = 0, ret = 0;
     int             connfd = 0;
 
     char             data[64] = {0};
      int             datalen = 0;
     
    unsigned char  *out = NULL;
    int             outlen = 0;
    
    ThreadInfo         *pThreadInfo = (ThreadInfo *)arg;
    void             *handle = pThreadInfo->handle; //

    
    //客户端 socket池 获取一条连接 
    ret = sckCltPool_getConnet(handle, &connfd);
    if (ret != 0)
    {
        printf("func sckCltPool_getConnet() err:%d\n", ret);
        return NULL;
    }
    
    for (i=0; i<pThreadInfo->iLoop; i++)
    {
        //客户端 socket池 发送数据 
        memset(data, 0, sizeof(data));
        sprintf(data, "第%d线程, 第%d圈", pThreadInfo->iArrayIndex, i+1);
        ret = sckCltPool_send(handle, connfd,  data, strlen(data));
        if (ret == Sck_ErrPeerClosed)
         { 
             printf("sckCltPool_send 客户端检测到 服务器已经关闭 退出\n");
             break;    
         }
         else if (ret == Sck_ErrTimeOut)
         {
             printf(" sckCltPool_send timeout \n");
             break;
         }
         else if (ret != 0)
         {
             printf("fun sckServer_rev() err:%d \n", ret);
             break;
         }

        //客户端 socket池 接受数据
        ret =  sckCltPool_rev(handle, connfd, &out, &outlen); //1
        if (ret == Sck_ErrPeerClosed)
         { 
             printf("sckCltPool_rev 客户端检测到 服务器已经关闭 退出\n");
             break;    
         }
         else if (ret == Sck_ErrTimeOut)
         {
             printf(" sckCltPool_rev timeout \n");
             break;
         }
         else if (ret != 0)
         {
             printf("fun sckCltPool_rev() err:%d \n", ret);
             break;
         }
         printf("客户端 out:%s \n", out);
         sck_FreeMem((void **)&out);
    }
    
    //客户端 socket池 把连接放回 socket池中 
    sckCltPool_putConnet(handle, connfd, 0); //0正常 1
    
    if (arg != NULL) free(arg);
    
     return NULL;
 }
 
int  main()
{
    int         ret = 0, i = 0;
    char         *ip = "127.0.0.1"; 
    int         port = 8001;
    int         time = 3;
    int         connfd = 0;
    
    int            iLoop = 0; //圈数
    int            iThreadNum = 0 ; //线程数
    
    void         *handle = NULL;
    pthread_t         pidArray[1024]; 
    
    //ThreadInfo             threadInfo;
    //memset(&threadInfo, 0, sizeof(ThreadInfo));
    
    SCKClitPoolParam            sckClitPoolParm;
    memset(&sckClitPoolParm, 0, sizeof(SCKClitPoolParam));
    strcpy(sckClitPoolParm.serverip,  "127.0.0.1");
    sckClitPoolParm.serverport = 8001;
    sckClitPoolParm.bounds = 20;  //node: 客户端线程池的个数是10个
    sckClitPoolParm.connecttime = 3;
    sckClitPoolParm.sendtime = 3;
    sckClitPoolParm.revtime = 3;
    
    
    printf("\n请输入线程的个数: ");
    scanf("%d", &iThreadNum);
    
    printf("\n请输入每个线程运行圈数: ");
    scanf("%d", &iLoop);
    
    if (iThreadNum >= 1024)
    {
        printf("iThreadNum大于1024\n");
        return 0;
    }

    //客户端 socket池初始化
    ret = sckCltPool_init(&handle,  &sckClitPoolParm);
    if (ret != 0)
    {
        printf("func  sckCltPool_init() err:%d \n ", ret);
        return ret;
    }
    
    //启动多线程 
    for (i=0; i<iThreadNum; i++)
    {
        ThreadInfo *pInfo = (ThreadInfo *)malloc(sizeof(ThreadInfo));
        pInfo->handle = handle;              //alt + 鼠标键左键拖动 
        pInfo->iLoop =  iLoop;
        pInfo->iArrayIndex = i + 1;
        pthread_create(&pidArray[i], NULL, myclient_startroutine, (void *)pInfo);
    }
    
    
    //主进程 等待子线程 结束
    for (i=0; i<iThreadNum; i++)
    {
         pthread_join(pidArray[i], NULL);
    }
    
    
    //客户端 socket池 销毁连接
    sckCltPool_destroy(handle);

    printf("client hello....\n");
    return 0;
}
a_client4.c

>make

>./a_server

打开另一个终端,切换到test目录下,执行>./a_client4,然后查看原终端的数据接收情况。

 

三、安全传输平台项目—统一共享内存组件

1、常见IPC

 

2、简单内存模型分析

 

3、共享内存操作函数—shmget

 

4、共享内存操作函数—shmat_dt

 

5、共享内存操作函数—shmctl

 

6、Linux内核管理共享内存方法

 

7、共享内存操作函数接口

 

 

四、客户端服务器密钥协商预说明

 

在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值