首页 > 其他分享 >两个线程共享一个套接字,其中一个线程使用sendmsg函数不断发送消息到该套接字,另一个线程使用recvmsg函数不断接收该套接字的消息,并打印出来的功能

两个线程共享一个套接字,其中一个线程使用sendmsg函数不断发送消息到该套接字,另一个线程使用recvmsg函数不断接收该套接字的消息,并打印出来的功能

时间:2023-12-15 10:55:40浏览次数:34  
标签:函数 sizeof iov struct 线程 msg 接字 message addr

以下是使用C语言写的一段代码,实现两个线程共享一个套接字,其中一个线程使用sendmsg函数不断发送消息到该套接字,另一个线程使用recvmsg函数不断接收该套接字的消息,并打印出来的功能

点击查看代码
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <pthread.h> 
 
 
int sockfd; 
 
 
void *send_func(void *arg) 
{ 
    while(1) 
    { 
        // 获取要发送的消息 
        char msg[1024]; 
        printf("请输入要发送的消息:\n"); 
        if(fgets(msg, 1024, stdin) == NULL) 
        { 
            printf("fgets error!\n"); 
            exit(1); 
        } 
 
 
        // 构造发送消息 
        struct sockaddr_in server_addr; 
        memset(&server_addr, 0, sizeof(server_addr)); 
        server_addr.sin_family = AF_INET; 
        server_addr.sin_port = htons(8000); 
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
 
 
        struct msghdr message; 
        struct iovec iov[1]; 
        char ctrl[sizeof(struct cmsghdr) + sizeof(int)]; 
        memset(&message, 0, sizeof(struct msghdr)); 
        memset(ctrl, 0, sizeof(ctrl)); 
 
 
        iov[0].iov_base = msg; 
        iov[0].iov_len = strlen(msg); 
        message.msg_name = &server_addr; 
        message.msg_namelen = sizeof(server_addr); 
        message.msg_iov = iov; 
        message.msg_iovlen = 1; 
        message.msg_control = ctrl; 
        message.msg_controllen = sizeof(ctrl); 
 
 
        size_t len = strnlen(msg, 1024) + 1; 
 
 
        struct cmsghdr *p; 
        p = CMSG_FIRSTHDR(&message); 
        p->cmsg_len = sizeof(ctrl); 
        p->cmsg_level = SOL_SOCKET; 
        p->cmsg_type  = SCM_RIGHTS; 
        *(int *)CMSG_DATA(p) = sockfd; 
 
 
        if(sendmsg(sockfd, &message, 0) == -1) 
        { 
            perror("sendmsg error!"); 
            exit(1); 
        } 
 
 
        sleep(1);  // 模拟不断发送消息 
    } 
} 
 
 
void *recv_func(void *arg) 
{ 
    while(1) 
    { 
        // 构造接收消息 
        struct sockaddr_in client_addr; 
        socklen_t addrlen = sizeof(client_addr); 
        struct msghdr message; 
        struct iovec iov[1]; 
        char ctrl[sizeof(struct cmsghdr) + sizeof(int)]; 
        memset(&message, 0, sizeof(struct msghdr)); 
        memset(ctrl, 0, sizeof(ctrl)); 
 
 
        iov[0].iov_base = malloc(1024); 
        iov[0].iov_len = 1024; 
        message.msg_name = &client_addr; 
        message.msg_namelen = addrlen; 
        message.msg_iov = iov; 
        message.msg_iovlen = 1; 
        message.msg_control = ctrl; 
        message.msg_controllen = sizeof(ctrl); 
 
 
        struct cmsghdr *p; 
        p = CMSG_FIRSTHDR(&message); 
        p->cmsg_len = sizeof(ctrl); 
        p->cmsg_level = SOL_SOCKET;  
        p->cmsg_type = SCM_RIGHTS;   
        *(int *)CMSG_DATA(p) = sockfd; 
 
 
        if(recvmsg(sockfd, &message, 0) == -1) 
        { 
            perror("recvmsg error!"); 
            free(iov[0].iov_base); 
            exit(1); 
        } 
 
 
        // 输出接收到的消息 
        char recvmsg[1024]; 
        strncpy(recvmsg, iov[0].iov_base, iov[0].iov_len); 
        recvmsg[iov[0].iov_len] = '\0'; 
        printf("收到消息:%s", recvmsg); 
 
 
        free(iov[0].iov_base); 
    } 
} 
 
 
int main(int argc, char *argv[]) 
{ 
    // 创建套接字 
    sockfd = socket(AF_INET, SOCK_DGRAM, 0); 
    if(sockfd == -1) 
    { 
        perror("socket error!"); 
        return 0; 
    } 
 
 
    // 绑定套接字 
    struct sockaddr_in addr; 
    memset(&addr, 0, sizeof(addr)); 
    addr.sin_family = AF_INET; 
    addr.sin_port = htons(8000); 
    addr.sin_addr.s_addr = htonl(INADDR_ANY); 
 
 
    if(bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) 
    { 
        perror("bind error!"); 
        return 0; 
    } 
 
 
    // 创建两个线程,一个发送消息,一个接收消息 
    pthread_t send_tid, recv_tid; 
    if(pthread_create(&send_tid, NULL, send_func, NULL) != 0) 
    { 
        perror("pthread_create error!"); 
        return 0; 
    } 
 
 
    if(pthread_create(&recv_tid, NULL, recv_func, NULL) != 0) 
    { 
        perror("pthread_create error!"); 
        return 0; 
    } 
 
 
    // 等待线程结束 
    if(pthread_join(send_tid, NULL) != 0) 
    { 
        perror("pthread_join error!"); 
        return 0; 
    } 
 
 
    if(pthread_join(recv_tid, NULL) != 0) 
    { 
        perror("pthread_join error!"); 
        return 0; 
    } 
 
 
    // 关闭套接字 
    close(sockfd); 
 
 
    return 0; 
} 


标签:函数,sizeof,iov,struct,线程,msg,接字,message,addr
From: https://www.cnblogs.com/cyj22/p/17902887.html

相关文章

  • shell补-特殊玩法-优化显示加入成功失败标识函数
    shell补-特殊玩法-优化显示加入成功失败标识函数加载函数文件/etc/init.d/functionsaction"******"/bin/true####正常显示action"******"/bin/false####失败显示[root@localhost~]#./etc/init.d/functions[root@localhost~]#action......
  • 38system函数与popen函数的比较
      importosr'''os.system和os.popen函数的对比。输出内容存在中文字符时,os.system回显会出现乱码,而os.popen不会。'''#执行popen函数defdoPopen():#执行命令,返回一个迭代对象给cmdcmd=os.popen('ipconfig/all')#cmd.readlines()返回一......
  • 线性探测法的查找函数
    #include<stdio.h>#defineMAXTABLESIZE100000/*允许开辟的最大散列表长度*/typedefintElementType;/*关键词类型用整型*/typedefintIndex;/*散列地址类型*/typedefIndexPosition;/*数据所在位置与散列地址是同一类型*//*散列单元状态类......
  • 线程的安全问题
    publicclassThreadDemo{publicstaticvoidmain(String[]args){/*需求:某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票*///创建线程对象......
  • 成员函数指针做回调参数总结 踩坑
    成员函数指针做回调参数总结踩坑一、程序升级后,在linux上编译提示错误:warning:convertingfrom‘int(MyClass::)()’to‘void()()’[-Wpmf-conversions]void(myStoredFunction)(void)=(GENERIC_FUNC_TYPE)memberFunc;//Compilerwarning二、出现这个情况是因为,程......
  • 函数实现一维数组基本操作
    论如何用一个代码实现一堆数字的排序,删除,插入,查找。这当然少不了我们在数组上的操作,将这些看成一个个小功能,接下来我们为了使结构直观,这里我用函数来实现这些功能首先是声明//功能voidFunction();//排序voidSort(inti,intnum);//查找voidFind(intz);//插入voidIn......
  • 多线程常用方法
    publicclassThreadDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{/*StringgetName()返回此线程的名称voidsetName(Stringname)设置线程的名字(构造方法......
  • 第六章 消息认证和哈希函数 —— 现代密码学(杨波)复习题
    第六章一、填空1.通信双方A和B通信,则可能发生哪两种形式的抵赖或欺骗?2.数字签名能够抵抗不可否认性攻击的原因是________________________________3.基于公钥加密的数字签名方式中,加密的消息应该是________________________4.直接方式的数字签名的公共弱点是______________......
  • 无涯教程-Java - acos()函数
    该方法返回指定双精度值的反余弦值。acos()-语法doubleacos(doubled)这是参数的详细信息-d - 双精度数据类型。acos()-返回值此方法返回指定双精度值的反余弦。acos()-示例publicclassTest{publicstaticvoidmain(Stringargs[]){double......
  • 【TCP】并发服务器<线程>
    //并发服务器-线程#include<stdio.h>#include<strings.h>//bzero#include<unistd.h>//close#include<sys/socket.h>//socket#include<netinet/in.h>//structsockaddr_in#include<arpa/inet.h>//inet_addr#include&......