首页 > 安全资讯 >

简单的多线程数据传输

16-10-04

为创建一份小型的工程代码,自己想出一个简单的数据传输任务。主进程创建四个线程,st1,st2,st3,rt,让前三个线程向最后一个线程灌包,最后一个线程接收数据包。目的IP: 10 21 100 152目的端口:9001各个进程被创建后立即进行相应的工作,灌包或者收包。

说明

为创建一份小型的工程代码,自己想出一个简单的数据传输任务。
主进程创建四个线程,st1,st2,st3,rt,让前三个线程向最后一个线程灌包,最后一个线程接收数据包。
目的IP: 10.21.100.152
目的端口:9001
各个进程被创建后立即进行相应的工作,灌包或者收包。rt接收到数据包后打印出相应的信息。

makefile

工程文件的编译会接触到makefile,下面是总结的常用的makfile变量

变量 意义
AR 静态库打开包命令的名字,default:ar
ARFLAGS 静态库打开包命令的选项,default:rv
AS 汇编器的名字,default: as
ASFLAGS 汇编器的选项
CC C编译器的名字,default: cc
CFLAGS C编译器的选项
CXX c++编译器的名字,default: g++
CXXFLAGS c++编译器的选项
CPP C预处理器的名字,default: $(CC) -E
CPPFLAGS C预处理器的选项
LD 链接器的名字, default: 1d
LDFLAGS 链接器的选项
TARGET_ARCH 和目标平台相关的命令行选项
OUTPUT_OPTION 输出的命令行选项,default: -o $@
LINK.o 把.o文件链接在一起的命令行,default: $(CC) $(LDFLAGS) $(TARGET_ARCH)
LINK.c 把 .c 文件链接在一起的命令行, default: $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
LINK.cc 把 .cc 文件(C++源文件)链接在一起的命令行, default: $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
COMPILE.c 编译.c文件的命令行, default: $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
COMPILE.cc 编译 .cc 文件的命令行, default: $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
RANLIB 静态库的符号索引表
CROSS_COMPILE 编译器前缀
ARCH CPU体系结构

另外一些可能用到的:
STRIP: 去空格函数,去除开头和结尾出现的空字符
addprefix: 加前缀函数

$(addprefix , , ...)
该函数将前缀  加到各个  的前面去。

代码结构

这里写图片描述
图中的.a文件和.d文件是编译后产生的。
.a文件是静态库文件,.d文件为源文件的依赖关系的完整规则。

code

common.h

#ifndef COMMON_H
#define COMMON_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define Len 20
#define Num 10
#define TASK_JOIN 1

typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef int INT32;
typedef struct msg{
    UINT8 context[Num][Len];
}Msg;

pthread_t g_st1;
pthread_t g_st2;
pthread_t g_st3;
pthread_t g_rt;
int g_rt_recv_sock;
struct sockaddr_in g_sendto;
struct sockaddr_in g_recvfr;

pthread_t create_pthread(INT32 prior, INT32 policy,
    INT32 state, void *fn, void *args_p);

void *msg_malloc(UINT8 dex);

void handler(int arg);

int recv_sock_set(UINT16 PORT);

struct sockaddr_in send_sock_set(char *IP, UINT16 PORT);

#endif

common.c

#include "../inc/common.h"

pthread_t create_pthread(INT32 prior, INT32 policy,
    INT32 state, void *fn, void *args_p)
{
    pthread_attr_t attr;
    struct sched_param param;
    pthread_t taskid;
    INT32 ret;

    pthread_attr_init(&attr);
    pthread_attr_setschedpolicy(&attr, policy); /* 调度策略 */
    param.sched_priority = prior;  /* 设定优先级 */
    pthread_attr_setschedparam(&attr, ¶m);

    /* PTHREAD_SCOPE_SYSTEM: kernel level thread, PTHREAD_SCOPE_PROCESS: user level thread */
    /* 设置线程优先级的有效范围,PTHREAD_SCOPE_SYSTEM表示和系统中所有线程竞争 */
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

    /* PTHREAD_CREATE_DETACHED : detachstate thread 相分离线程
      PTHREAD_CREATE_JOINABLE : joinable thread 可会合线程 */
    if (state != 1) {
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    }

    /* PTHREAD_INHERIT_SCHED: inherit father thread's attr
     * PTHREAD_EXPLICIT_SCHED: use pthread_create() attr */
    pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED);

    if ((ret = pthread_create(&taskid, &attr, fn, args_p)) != 0) {
        printf("fail to create pthread: ret=%d\n", ret);
        /* 取得用户的识别码,等于0则是root */
        if(getuid() != 0){
            printf("Please run app with root user\n");
        }
        return -1;
    }
    else{
        pthread_attr_destroy(&attr);
        return taskid;
    }
}

void *msg_malloc(UINT8 dex){
    void *mem = malloc(sizeof(Msg));
    Msg *g_msg = (Msg *)mem;
    int i;
    for(i=0;icontext[i],str);
    }
    return mem;
}

int recv_sock_set(UINT16 PORT){
    int sock_fd = socket(AF_INET,SOCK_DGRAM,0);
    if(sock_fd == -1){
        perror("socket ");
        exit(1);
    }
    struct sockaddr_in serv;
    bzero(&serv,sizeof(serv));
    serv.sin_family = AF_INET;
    serv.sin_addr.s_addr = htonl(INADDR_ANY); //inet_addr("");
    serv.sin_port = htons(PORT);
    if(bind(sock_fd,(struct sockaddr *)&serv, sizeof(serv)) == -1){
        perror("bind ");
        exit(1);
    }
    return sock_fd;
}

struct sockaddr_in send_sock_set(char *IP, UINT16 PORT){
    struct sockaddr_in send;
    bzero(&send,sizeof(send));
    send.sin_family = AF_INET;
    send.sin_addr.s_addr = inet_addr(IP);
    send.sin_port = htons(PORT);
    return send;
}

void handler(int arg){
    printf("ctrl c finish process.\n");
    exit(0);
}

main.c

#include "../inc/common.h"

extern void *st1_thread_run(void *args);
extern void *st2_thread_run(void *args);
extern void *st3_thread_run(void *args);
extern void *rt_thread_run(void *args);

int main(){
    printf("main process start.\n");
    signal(SIGINT,handler);
    pthread_t st1, st2, st3, st4;
    char *sendto_IP = "10.21.100.152";
    UINT16 PORT = 9000;
    g_sendto = send_sock_set(sendto_IP,PORT);
    g_rt = create_pthread(90,SCHED_FIFO, TASK_JOIN,rt_thread_run,"rt_thread_run");
    /*在本地实验,如果三个发送数据的线程优先级是一样的,那么第一个线程在后期争夺资源不如另外两个,所以将其调高了一点*/
    g_st1 = create_pthread(91,SCHED_FIFO, TASK_JOIN,st1_thread_run,"st1_thread_run");
    g_st2 = create_pthread(92,SCHED_FIFO, TASK_JOIN,st2_thread_run,"st2_thread_run");
    g_st3 = create_pthread(92,SCHED_FIFO, TASK_JOIN,st3_thread_run,"st3_thread_run");
    if(g_rt > 0)pthread_join(g_rt, NULL);  /* 等待st1线程结束 */
    else printf("create thread rt failed.\n");
    exit(0);
}

rt.c

#include "../inc/common.h"

void *rt_thread_run(void *args){
    printf("rt thread start work!\n");
    g_rt_recv_sock = recv_sock_set(9000);
    void *get_msg = malloc(Len);
    if(get_msg == NULL){
        perror("get_msg malloc ");
        exit(1);
    }
    while(1){
        int recv_len = sizeof(g_recvfr);
        int ret = recvfrom(g_rt_recv_sock,get_msg,Len,0,(struct sockaddr*)&g_recvfr,&recv_len);
        if(ret > 0){
            printf("%s\n",(char *)get_msg);
        }
        else printf("here is no data.\n");
    }
    if(get_msg) free(get_msg);
    return NULL;
}

st1.c

#include "../inc/common.h"

void *st1_thread_run(void *args){
    printf("st1 thread start work!\n");
    //void *msg = msg_malloc((UINT8)1);
    char *get_msg = "this is st1 msg.";
    g_st1 = socket(AF_INET,SOCK_DGRAM,0);
    if(g_st1 == -1){
        perror("socket ");
        exit(1);
    }
    while(1){
        int i;
        /*
        Msg *send_msg = (Msg *)msg;
        for(i=0;icontext[i],strlen(send_msg->context[i]),0,
             (struct sockaddr *)&g_sendto,sizeof(g_sendto));
        }*/
        int ret = sendto(g_st1,get_msg,strlen(get_msg),0,(struct sockaddr *)&g_sendto,sizeof(g_sendto));
        if(ret <= 0){
            perror("st1 send to ");
        }
        sleep(1);
        //send_msg = NULL;
    }
    return NULL;
}

st2.c

#include "../inc/common.h"

void *st2_thread_run(void *args){
    printf("st2 thread start work!\n");
    char *get_msg = "this is st2 msg.";
    g_st2 = socket(AF_INET,SOCK_DGRAM,0);
    if(g_st2 == -1){
        perror("socket ");
        exit(1);
    }
    while(1){
        int i;
        int ret = sendto(g_st2,get_msg,strlen(get_msg),0,(struct sockaddr *)&g_sendto,
                sizeof(g_sendto));
        if(ret <= 0){
            perror("st2 send to ");
        }
        sleep(1);
    }
    return NULL;
}

st3.c

#include "../inc/common.h"

void *st3_thread_run(void *args){
    printf("st3 thread start work!\n");
    char *get_msg = "this is st3 msg.";
    g_st3 = socket(AF_INET,SOCK_DGRAM,0);
    if(g_st3 == -1){
        perror("socket ");
        exit(1);
    }
    while(1){
        int i;
        int ret = sendto(g_st3,get_msg,strlen(get_msg),0,(struct sockaddr *)&g_sendto,
                sizeof(g_sendto));
        if(ret <= 0){
            perror("st3 send to ");
        }
        sleep(1);
    }
    return NULL;
}

/pthread_data_transfer/makefile

PWD := $(shell pwd)
IncDir := $(PWD)/../inc

INCLUDE_H_DIR := $(IncDir)

DEBUG := -g

MAIN := $(PWD)/src
MAIN_OBJ   := $(MAIN)/*.o

.PHONY:all 
all:lib 
    $(CC)  -o main  $(MAIN_OBJ) -lm -lpthread -lrt 

.PHONY:lib
lib:
    $(MAKE) -C $(MAIN)

.PHONY:clean
clean:
    make clean -C $(MAIN)
    rm -f  *.o *.a

/pthread_data_transfer/src/makefile

# source file
C_SOURCE := $(shell find -name '*.c')
#Get object file generated by C source file
C_OBJS := $(subst .c,.o,$(C_SOURCE))
#Get dependent file 
DEPS := $(subst .o,.d,$(C_OBJS))

.PHONY:all
all:$(C_OBJS)
$(C_OBJS):%.o:%.c
    $(CC) $(DEBUG) $(CFLAGS) -c $< -o $@

ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEPS)
endif

%.d:%.c
    $(CC) -M $(CFLAGS) $< > $@.$$$$;\
    sed 's,$(subst .c,.o,$(notdir $<)),$(subst .c,.o,$<) $@,g' < $@.$$$$ > $@;\
    rm -f $@.$$$$

.PHONY:clean
clean:
    rm -rf *.o  *.a *.d

得到的结果 (用root: ./main > read):

main process start.
rt thread start work!
st1 thread start work!
this is st1 msg.
st2 thread start work!
this is st2 msg.
st3 thread start work!
this is st3 msg.
this is st2 msg.
this is st3 msg.
this is st1 msg.
this is st2 msg.
this is st3 msg.
this is st1 msg.
this is st3 msg.
this is st2 msg.
this is st1 msg.
this is st3 msg.
this is st2 msg.
this is st1 msg.
ctrl c finish process.
相关文章
最新文章
热点推荐