0

我正在多线程环境中开发客户端 - 服务器应用程序。客户端和服务器都有两个线程。主线程使用套接字(IPv4-TCP)发送数据,客户端相应的主线程接收数据。发送和 recv 函数是作为我设计的一部分的自定义函数。我在另一个线程中为服务器上的 SIGUSR1、SIGUSR2 和 SIGINT 设置了三个信号处理程序。在接收 SIGINT 时,会进行线程清理以优雅地关闭所有套接字并终止线程,而在接收 SIGUSR1,SIGUSR2 时,我设置了两个全局标志,它们在同一线程中使用,并在主线程中自定义发送函数来做一些事情将套接字 id 切换为 IPv6 的操作。(有逻辑让客户端知道套接字已更改为 IPv6)。自定义发送/接收函数有 malloc 和 free 函数。

问题是当我在终端上使用 kill -SIGUSR1 pid 向服务器进程发送信号时,在一些发送调用之后,传输挂起。对于每个发送调用,我正在发送数据包,它具有要发送的数据大小、实际数据和一个可选标志,指示下一个数据将在另一个套接字 id 上。当我在客户端打印数据大小时,在收到信号后某些 recv 调用后它全部为零。我确信 SIGNAL 一定是原因,因为当我反转操作并让客户端将数据发送到服务器(上传)使用相同的发送/接收功能它工作正常。我能够切换套接字 ID。在这两种情况下,我都向服务器进程发送信号。recv 函数 recvs 直到数据量与该数据包的大小部分中指示的相同,因为 TCP 是基于流的。我不确定为什么在接收信号后进行一些发送调用后大小变为零。我使用了互斥锁,除了在设置信号处理程序部分时使用了全局变量。代码如下。

线程 2:

fn_sigUsrHandler(SIGUSR1);
fn_sigUsrHandler(SIGUSR2);
fn_sigUsrHandler(SIGINT);
void fn_sigUsrHandler(int p_signal)
{
/* Signal handler structure */
struct sigaction vl_sigStruct;
int vl_errno;
char vl_err_buff[256];

vl_sigStruct.sa_flags = SA_RESTART;
sigemptyset(&vl_sigStruct.sa_mask);


switch(p_signal)
{
    case SIGUSR1:
        vl_sigStruct.sa_handler = fn_switch;
        break;
    case SIGUSR2:
        vl_sigStruct.sa_handler = fn_switch;
        break;
    case SIGINT:
        vl_sigStruct.sa_handler = fn_cleanUP;
        break;
}

vl_errno = sigaction(p_signal, &vl_sigStruct, NULL);
if (vl_errno == -1) {
    fprintf(stdout,"Control Thread-Error in catching SIGUSR1:%s\n",fn_strerror_r(errno,vl_err_buff));
    exit(EXIT_FAILURE);
}


void fn_switch(int st_val){
/*
pthread_mutex_lock(&socket_mutex_3);
ip_proto_switch = 1;
vg_ctrlpacket_sent =1;
pthread_mutex_unlock(&socket_mutex_3);
*/

vg_proto_switch = 1;
vg_ctrlpacket_sent =1;

fprintf(stdout,"Signalled to switch\n");
}

主线程:

int vl_err; /* Number of bytes sents */
char err_buff[256]; /* Buffer to hold error message*/
int vl_change_sock = 0;

if(p_flags != NO_DATA_TX)
{
    char *vl_bufData;
    st_packetData vst_packet; /* Structure holding the data to be sent */
    unsigned int vl_packetSize = sizeof(unsigned int) +     sizeof(vst_packet.vst_pad) + (int)p_len;//sss
    vl_bufData = (char *)malloc(vl_packetSize);
    memset(vl_bufData,'\0',vl_packetSize);

    pthread_mutex_lock(&socket_mutex_2);
        if(vg_ctrlpacket_recv == 1){
            ///strcpy(vst_packet.vst_pad,vg_change_socket);
            vl_change_sock = 1;
            vg_ctrlpacket_recv = 0;                 
            fprintf(stdout,"len:%d\n",strlen(vst_packet.vst_pad));
        }
    pthread_mutex_unlock(&socket_mutex_2);


    if(vl_change_sock == 1){


            char *vl_bufData2 = vl_bufData+sizeof(unsigned int);
            snprintf(vl_bufData2,(int)p_len,"%s",p_buffer);
            //memcpy(vl_bufData+sizeof(unsigned int)+(int)p_len,vg_change_socket,sizeof(vst_packet.vst_pad));//sss
        */

        snprintf(vl_bufData,sizeof(unsigned int)+1,"%u",vl_packetSize);
        memcpy(vl_bufData+sizeof(unsigned int),p_buffer,(int)p_len);//sss
        snprintf(vl_bufData+sizeof(unsigned int)+(int)p_len,sizeof(vst_packet.vst_pad)+1,"%s",vg_change_socket);

        vl_err = send(p_mysocket->socket_id,vl_bufData,vl_packetSize,p_flags);
        if(vl_err == -1)
        {
            fprintf(stderr,"mysocket-fn_send-TCP-vl_err err :%s\n",fn_strerror_r(errno,err_buff));//HS
            exit(EXIT_FAILURE);//HS 
        }

        if(debug > 0)
            fprintf(stdout,"The socket before change is :%d client side \n",p_mysocket->socket_id);

        if((p_mysocket->socket_id) == p_mysocket->sock_id[0])
            p_mysocket->socket_id = p_mysocket->sock_id[1];
        else
            p_mysocket->socket_id = p_mysocket->sock_id[0];

        if(debug > 0)
            fprintf(stdout,"The socket after change is :%d client side \n ",p_mysocket->socket_id);

    }
    else{
        snprintf(vl_bufData,sizeof(unsigned int)+1,"%u",vl_packetSize);
        memcpy(vl_bufData+sizeof(unsigned int),p_buffer,(int)p_len);//sss

        vl_err = send(p_mysocket->socket_id,vl_bufData,vl_packetSize,p_flags);
        if(vl_err == -1)
        {
            fprintf(stderr,"mysocket-fn_send-TCP-vl_err err :%s\n",fn_strerror_r(errno,err_buff));//HS
            exit(EXIT_FAILURE);//HS 
        }

    }   

    if(debug > 2){
        /*fprintf(stdout,"size of st_packetData:%d\n",sizeof(st_packetData));
        fprintf(stdout,"vl_packetSize:%d\n",vl_packetSize); 
        fprintf(stdout,"Memcopied-data:%s\n",vst_packet.vst_data);
        fprintf(stdout,"Memcopied-pad:%s\n",vst_packet.vst_pad);
        fprintf(stdout,"Memcopied-size:%d\n",vst_packet.vst_size);//sss
        fprintf(stdout,"Data from buffer:%s\n",p_buffer);
        fprintf(stdout,"data:%s\n",vl_bufData+sizeof(vst_packet.vst_size)+sizeof(vst_packet.vst_pad));*/
        fprintf(stdout,"Copied data:%-10.6s\n",vl_bufData);
        fprintf(stdout,"---------------------------\n");
    }


    //if(vl_err >=(sizeof(vst_packet.vst_size)+ sizeof(vst_packet.vst_pad))) //sss
    if(vl_err >=(sizeof(unsigned int)+ strlen(vg_change_socket)))
    {
        vl_err = vl_err-(sizeof(unsigned int) + strlen(vg_change_socket));//sss
    }
    if(debug > 2)
    {
        fprintf(stdout,"The socket id is :%d.. Thread:%s\n",p_mysocket->socket_id,p_mysocket->vst_nm_thread);
        fprintf(stdout,"The data tx %d.. Thread:%s\n",vl_err,p_mysocket->vst_nm_thread);
    }

    free((void *)vl_bufData);

}
else
{   
    vl_err = send(p_mysocket->socket_id,p_buffer,p_len,0);
    if(vl_err == -1)
    {
        fprintf(stderr,"mysocket-fn_send-TCP-vl_err err :%s\n",fn_strerror_r(errno,err_buff));//HS
        exit(EXIT_FAILURE);//HS 
    }
    if(debug>1)
    {
        fprintf(stdout,"The socket id is :%d.. Thread:%s\n",p_mysocket->socket_id,p_mysocket->vst_nm_thread);
        fprintf(stdout,"The data tx %d.. Thread:%s\n",vl_err,p_mysocket->vst_nm_thread);
    }
}
/* return number of bytes sent */
return vl_err;
}
4

1 回答 1

0

谢谢大家的回复。经过一些进一步的研究,我发现 SIGUSR1 是由主线程而不是控制线程处理的。由于调用的 fn_recv 具有 malloc 之类的函数,我认为它不是可重入的,因此导致了问题。

我通过屏蔽 SIGUSR1 信号并创建一个单独的线程来设置信号处理程序而不是控制线程来解决它,以避免干扰系统/函数调用。我在新线程中取消屏蔽 SIGUSR1 信号,以确保它仅由这个新线程处理。我现在可以多次传输数据并切换套接字 ID 而不会出现停顿。如果有人需要更多详细信息,请告诉我。基本上在主线程中屏蔽信号并在子线程中取消它就可以了!

于 2012-08-23T18:12:12.580 回答