无法拆分在具有处理c

时间:2017-02-26 11:46:44

标签: c multithreading sockets server client

我已经编写了一个服务器来处理带线程的多组客户端。唯一的问题是,即使我已经锁定了关键部分,它也不会在客户端之间平均分配工作。

这是服务器

#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <math.h>

void *con(void *);
int r, x, convr, convx, flag;
double sqrtr,doubler;
pthread_mutex_t var;

int main(int argc,char *argv[]){
    srand(time(NULL));
    r=rand();

    r=(r%(21474836146-2000000000))+2000000000;
    r=340;
    doubler=(double)r;
    x=2;
    convr=htonl(r);
    convx=htonl(x);

    sqrtr=sqrt(doubler);
    flag='p';

    int soc, clientsoc, *new, asize;
    struct sockaddr_in server, client;

    soc=socket(AF_INET,SOCK_STREAM,0);
    if(soc==-1){
        perror("Error creating socket");
    }

    server.sin_family=AF_INET;
    server.sin_addr.s_addr=INADDR_ANY;
    server.sin_port=htons(7897);

    if(bind(soc,(struct sockaddr *)&server,sizeof(server))<0){
        perror("Error binding socket");
        return 1;
    }
    if(listen(soc,5)!=0){
        perror("Error listening");  
    }
    int start='n';
    printf("Are you ready to start?  Don't continue until you have connected all the"
             " clients you with to use to the server.  (press y for yes)\n");
    start=getchar();
    while(start!='y'){
        printf("Are you ready to start?  Don't continue until you have connected all the"
             " clients you with to use to the server.  (press y for yes)\n");
        start=getchar();
    }
    asize=sizeof(struct sockaddr_in);
    while((clientsoc=accept(soc,(struct sockaddr *)&client,(socklen_t*)&asize))){
        pthread_t client_thread;

        new=malloc(1);
        *new=clientsoc;
        if(pthread_create(&client_thread,NULL,con,(void*) new)<0){
            perror("Error creating thread");
            return 1;
        }
        pthread_join(client_thread,NULL);
    }
    if(clientsoc<0){
        perror("Error accepting");
        return 1;
    }
    return 0;
}

//the handeler for a connection
void *con(void *socket){
    int soc=*(int*)socket;
    int flagtemp, flagtempconv;
    //what it will do here
    int rs;
    while(1){
        pthread_mutex_lock(&var);
        printf("Sending %d\n",r);
        if(write(soc,&convr,sizeof(convr))<0){
            printf("Failed to send");
            exit(1);
        }
        printf("Sending %d\n\n",x);
        if(write(soc,&convx,sizeof(convx))<0){
            printf("Failed to send");
            exit(1);
        }
        if(rs=read(soc,&flagtemp,sizeof(flagtemp))>0){
            flagtempconv=ntohl(flagtemp);
            printf("Received %d\n",flagtempconv);
            if(flagtempconv=='n')
                flag=flagtempconv;
            if(flag=='n'){
                printf("The numer %d is divisible by %d and is not prime\n",r,x);
                break;
            }else if(x>=sqrtr){
                printf("The number %d is prime\n",r);
                break;
            }
            x++;
            convx=htonl(x);
        } else if(rs==0){
            printf("Disconnected from client");
        } else if(rs<0){
            printf("Read error");   
        }
        pthread_mutex_unlock(&var);
    }
    close(soc);
    exit(0);
}

这是客户端

#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>

int main(int argc, char *argv[]){
    int r, x, convr, convx, flag, convflag, soc, mod;

    flag='p';

    struct sockaddr_in server;
    soc=socket(AF_INET,SOCK_STREAM,0);

    if(soc==-1){
        perror("Error creating socket");
    }

    server.sin_family=AF_INET;
    server.sin_addr.s_addr=inet_addr("127.0.0.1");
    server.sin_port=htons(7897);

    if(connect(soc, (struct sockaddr*)&server,sizeof(server))<0){
        perror("Error connecting");
        return 1;
    }
    //put what the socket will do here
    while(1){
        if(read(soc,&r,sizeof(r))<0){
            printf("Error receiving\n");
        }
        convr=ntohl(r);
        printf("Received %d\n",convr);
        if(read(soc,&x,sizeof(x))<0){
            perror("Error receiving");
        }
        convx=ntohl(x);
        printf("Received %d\n",convx);
        mod=convr%convx;
        printf("%d mod %d = %d\n",convr,convx,mod);
        if(mod==0){
            flag='n';
            convflag=htonl(flag);
        }
        printf("Sending %d\n\n",flag);
        if(write(soc,&convflag,sizeof(convflag),0)<0){
                printf("Failed to send");
                return 1;
            }
    }
    close(soc);
    return 0;
}

当我在multuple客户端上运行时,一个客户端完成所有工作。另一个客户端似乎在接收第一条消息时出错,并且没有说明它是接收还是没有接收到第二条消息。然后它似乎接收到我发送给它的两个整数,只有当它打印出来时才会将它们从htonl(int)转换回来。这是我在服务器和第一个客户端以及第二个客户端获取此程序的输出。此外,完成所有工作的客户端始终是我连接到服务器的第一个。另外,请不要建议不使用线程,因为我必须使用线程。

这是服务器的作用

  

kyle @ kyle-VirtualBox:/ media / sf_cs_470 $ ./lab4_server你准备好了吗?   开始?在连接所有客户端之前不要继续   与使用到服务器。 (按y表示是)y发送340发送2

     

收到110数字340可以被2整除,而不是素数

这是客户所做的所有工作

  

kyle @ kyle-VirtualBox:/ media / sf_cs_470 $ ./lab4_client收到340   收到2 340 mod 2 = 0发送110

     

收到340收到2 340 mod 2 = 0发送110

     

收到340收到2 340 mod 2 = 0发送110

这是无效的客户端

  

kyle @ kyle-VirtualBox:/ media / sf_cs_470 $ ./lab4_client接收错误   收到-924752754收到-25296896   -924752754 mod -25296896 = -14064498发送112

非常感谢你帮助我。同样,目标是尽可能在客户之间平均分配工作。

1 个答案:

答案 0 :(得分:1)

首先:这不是关于C的问题。这是关于POSIX线程的问题,关于BSD套接字等问题;但这些东西都不是C语言的一部分。如果您打算使用C,那么熟悉ISO 9899及其功能和不涵盖的内容是一个非常好的主意。

第二:请注意,即使使用正确编写的此类程序,在分布式系统中调度工作也不是一个小问题。您可以强制执行各种简单的排序,例如循环法,但是多线程服务器(特别是使用每个会话的线程模型)不太可能具有可预测的行为。

代码。

    if(pthread_create(&client_thread,NULL,con,(void*) new)<0){
        perror("Error creating thread");
        return 1;
    }
    pthread_join(client_thread,NULL);

此代码说:

  1. 创建一个帖子。
  2. 如果成功,请等待它终止。
  3. 您的调用线程将一直阻塞,直到子线程完成。你可能也没有首先创建一个线程。

    但这不是唯一的问题。考虑:

        new=malloc(1);
        *new=clientsoc;
    

    clientsock被定义为int。你真的在sizeof(int) == 1的平台上运行吗?只有当CHAR_BIT至少为16时,这才是真的,这是......不寻常的,我们应该说。你很可能在这里引起了未定义的行为,现在任何事情都可能发生。

    将硬编码值传递给malloc是一件坏事。不要做。尝试:

    new=malloc(sizeof *new);
    

    (另外,您可能希望将名称“new”视为标识符,以防您想将此代码移动到C ++。虽然坦率地说我的首选是永远不要使用C ++实现C源;如果你想要C ++,编写C ++。)

    我没有找其他问题。