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

发布时间 2023-12-15 10:55:18作者: 学好声韵辩四声

以下是使用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; 
}