多线程tcp server程序---小改

代码是别人的,作为例子跑跑。主要是做个修改标记,致谢前辈。

代码如下:

/*tcp_server.c*/



#include <sys/wait.h>//防退出添加

#include <stdlib.h> 
#include <stdio.h> 
#include <errno.h> 
#include <string.h> 
#include <netdb.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h>
#include <pthread.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#define portnumber 8500
#define buffer_size 10
/* -------mutex valibale ---------*/
pthread_mutex_t mutex_r,mutex_w;
char read_flag,write_flag;   
void read_pthread(void);
void write_pthread(void);
/*-------Glocal read/write data ----------------*/
char read_buffer[buffer_size];
char write_buffer[buffer_size];
/*-------Glocal conncetion ID-------------*/
int new_fd;
int sockfd;
int num ;

int main(int argc, char *argv[]) 
{ 
    /*
    int sockfd;
    int new_fd;
    */ 
    struct sockaddr_in server_addr; 
    struct sockaddr_in client_addr; 
    struct sigaction sa;//防退出添加
    int sin_size; 
    int nbytes;
    /*----------------define local variables,related to thread-----------------*/          
    int ret;
    pthread_t id1,id2;
    //initialize the mutex
    pthread_mutex_init(&mutex_r,NULL);
    pthread_mutex_init(&mutex_w,NULL);
    /* ---------------------related to network ---------------------------------*/
    if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) // AF_INET:IPV4;SOCK_STREAM:TCP
    { 
        fprintf(stderr,"Socket error:%s\n\a",strerror(errno)); 
        exit(1); 
    } 
    bzero(&server_addr,sizeof(struct sockaddr_in)); 
    server_addr.sin_family=AF_INET;                 // Internet
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);  
    server_addr.sin_port=htons(portnumber);         
    if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) 
    { 
        fprintf(stderr,"Bind error:%s\n\a",strerror(errno)); 
        exit(1); 
    } 
    if(listen(sockfd,5)==-1) 
    { 
        fprintf(stderr,"Listen error:%s\n\a",strerror(errno)); 
        exit(1); 
    } 
    printf("start listen...\n");

    sa.sa_handler = SIG_IGN;//防退出添加
    sigaction( SIGPIPE, &sa, 0 );//防退出添加
    while(1) 
    { 
        sin_size=sizeof(struct sockaddr_in);// This is must be in while()?
        printf("waiting for connection ----\n");
        if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1) 
        { 
            fprintf(stderr,"Accept error:%s\n\a",strerror(errno)); 
            exit(1); 
        } 
        fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr));
        /*------ create the read thread -------- */
        ret = pthread_create(&id1, NULL, (void*)read_pthread, NULL);
        if (ret)
        {
            printf("Create pthread error!\n");
            return 1;
        }
        printf("start the read_pthread successed \n");
        /*--------create the wirte thread----------------*/
          //启动写线程便会终止整个程序,不知为何??    
        ret = pthread_create(&id2, NULL, (void*)write_pthread, NULL);
            if (ret)
            {
                    printf("Create pthread error!\n");
                    return 1;
            }
        printf("start the write_pthread successed\n");

        printf("start to read/write data \n");
        /* -----------read and write data ------------------*/
        while(1)
        {       
            //How long time to check ?
            if(pthread_kill(id1,0)!=0)
            {
                printf("read_pthread is stoped ,\n");
                break;
            }           
            if(!pthread_mutex_lock(&mutex_r))
            {
                if(read_flag)
                {
                    //实际操作中,把read_buffer中数据传给main 循环中的变量
                    printf("Server received--%i ----%s \n",num,read_buffer);
                }

                pthread_mutex_unlock(&mutex_r);
            }
            usleep(20000);
            //close(new_fd);        
        } 
    } 
    close(sockfd);   //How to jump here ? 
    printf("Close socket !\n");
    exit(0); 
}

void write_pthread(void)
{
    /*
    int state;
    state=PTHREAD_CANCEL_DEFERRED;
    pthread_setcancelstate(state,&oldstate);
    */
    static int nbytes;
    static char buffer[buffer_size];
    while(1) //
    {
        /*这里进行互斥标志位的判断,把数据传递到buffer */
        /*
        pthread_mutex_lock(&mutex_w);
        write_flag=0;
        pthread_mutex_unlock(&mutex_w);
        */
        /*transfer datas */
        /*memcpy(read_buffer,buffer,nbytes);*/
            strcpy(buffer,"tcp_send ok");
        /*
        pthread_mutex_lock(&mutex_w);
        write_flag=1;
        pthread_mutex_unlock(&mutex_w);
             */
         /*string ->  char **/
            nbytes=write(new_fd,buffer,buffer_size);
        if(nbytes<0)
        {
            fprintf(stderr,"write error:%s\n\a",strerror(errno));
        }
        usleep(20000);
    }

}

//方法要对变量加上互斥锁
void read_pthread(void)
{
    static int nbytes;
    static char buffer[buffer_size];
    while(1)
    {
        nbytes=read(new_fd,buffer,buffer_size);
        num++;            
        if((nbytes==0)||(nbytes==-1))
        {
            if(nbytes==0)
            {   //the connection had be closed .
                printf("The connection is error !\n");
                break;
            }
            else
                fprintf(stderr,"Read Error:%s\n",strerror(errno)); 
            close(new_fd);  
            exit(1);         
         }
        //这里的加锁是可预见的
         /*-------mutex lock----------*/
        pthread_mutex_lock(&mutex_r);
        read_flag=0;
        pthread_mutex_unlock(&mutex_r);
        memcpy(read_buffer,buffer,nbytes);
        pthread_mutex_lock(&mutex_r);
        read_flag=1;
        pthread_mutex_unlock(&mutex_r);
    }
    printf("read_pthread is quit\n");
}

在断开client连接时候,服务器端进程退出的解决办法

文件中添加:

#include <sys/wait.h>
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigaction( SIGPIPE, &sa, 0 );
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值