2010-11-15 24 views
2

我想使用一个队列在2个线程之间传递消息,但到目前为止我还没有得到任何结果。当我收到消息并在发送消息之前打印消息的内容时,它似乎只是保持其值。我需要用1个服务器线程和多个客户端线程来实现它,但现在我只使用每个线程中的一个。这里是我的代码C - 在使用队列的线程之间传递消息的问题

struct msg        //struct for client requests to server 
{ 
     long mtype; 
     int numResources;   //number of resources to be requested 
     int ID;      //ID associated with client thread 
};           

int c1PID;        //process ID variable for client thread 1 
int serverPID; 

key_t key1; 
key_t keyS; 

int msqid1; 
int msqidS; 

int main(int arc, char *argv[]) 
{ 
     key1 = ftok(".", '1');  //queue for client thread 1 to receive msgs from server 
     msqid1 = msgget(key1, 666 | IPC_CREAT); 

     keyS = ftok(".", 's');       //general queue for server 
     msqidS = msgget(keyS, 666 | IPC_CREAT); 

     pthread_t threads[2];    //create an array of pthreads 

     if ((serverPID = pthread_create(&threads[0], NULL, server, NULL)) != 0) 
     { 
       perror("server thread"); 
       exit(1); 
     } 

     if ((c1PID = pthread_create(&threads[1], NULL, client, NULL)) != 0) 
     { 
       perror("client thread"); 
       exit(1); 
     } 

     pthread_exit(NULL); 
} 

void *server() 
{         
     struct msg request; 
     size_t size = sizeof(struct msg) - offsetof(struct msg, numResources); 

     while (1) 
     { 

       msgrcv(msqidS, &request, size, 2, 0); 

       printf("received: numResources requested = %d\n", request.numResources); 

       request.numResources = 9001; 

       printf("sending: numResources requested = %d\n", request.numResources); 

       msgsnd(msqid1, &request, size, 0); 

       sleep(1); 
     } 
} 

void *client() 
{ 
     struct msg request; 
     size_t size; 
     request.numResources = 0; 
     size = sizeof(struct msg) - offsetof(struct msg, numResources); 

     msgsnd(msqidS, &request, size, 0); 

     while(1) 
     { 
       msgrcv(msqid1, &request, size, 2, 0); 

       printf("received: numResources requested = %d\n", request.numResources); 

       request.numResources += 1;//(int)(ceil((double)(rand()%2)) + 1); 

       printf("sending: numResources requested = %d\n", request.numResources); 

       msgsnd(msqidS, &request, size, 0); 

       sleep(1); 
} 

我拿出我的很多的print语句,但它看起来是这样的:

Server thread: 
received: numResources = 9001; 
sending: numResources = 9001; 

client thread: 
received: numResources = 1; 
sending: numResources = 2; 

Server thread: 
received: numResources = 9001; 
sending: numResources = 9001; 

client thread: 
received: numResources = 2; 
sending: numResources = 3; 
+0

您是否试图实现一个客户端服务器程序,它将在两台独立的机器上运行,或者您将只有两个线程相互通信? – JonVD 2010-11-15 01:31:55

+0

他们只是在同一台机器上互相交谈 – Anon 2010-11-15 01:34:34

回答

0

编辑: 的的sizeof(结构MSG) - offsetof(结构味精,numResources );应该可以。

但是,根据docs,您的mtype需要为正整数。将它初始化为2,因为你对msgrecv的呼叫表示只接收消息类型2.

向所有的msgsnd/msgrecv调用添加错误检查,所以你确定你没有默默得到错误。

将错误检查添加到您的ftok和msgget调用中。

+0

我最初通过numResources来抵消它,因为我之前所说的队列教程说,在mtype之后立即由数据成员抵消。我尝试将其更改为ID,但似乎没有做任何事情。 – Anon 2010-11-15 01:37:13

+0

现在我通过offsetof(结构体味,ID)作为大小参数,仍然没有运气:/我会尝试添加错误消息发送/接收 – Anon 2010-11-15 01:48:03

+0

嗯,我把错误捕捉(如果发送/接收函数== -1,打印错误并退出),并返回“无效参数”。但是我尽可能接近我的教程指南,我不确定哪些论点是不正确的。 – Anon 2010-11-15 02:03:11

1

以下是运行时显示的工作状态。

program starting 
Msg sent from client 

*****In client thread***** 
Msg received by client 
received: numResources requested = 0 
sending: numResources requested = 1 
Msg sent from client 


*****In server thread***** 
Msg received by server 
received: numResources requested = 1 
sending: numResources requested = 9001 
Msg sent from server. 


*****In client thread***** 
Msg received by client 
received: numResources requested = 9001 
sending: numResources requested = 9002 
Msg sent from client 


*****In server thread***** 
Msg received by server 
received: numResources requested = 9002 
sending: numResources requested = 9001 
Msg sent from server. 


*****In client thread***** 
Msg received by client 
received: numResources requested = 9001 
sending: numResources requested = 9002 
Msg sent from client 


*****In server thread***** 
Msg received by server 
received: numResources requested = 9002 
sending: numResources requested = 9001 
Msg sent from server. 


*****In client thread***** 
Msg received by client 
received: numResources requested = 9001 
sending: numResources requested = 9002 
Msg sent from client 

紧接着又....

program starting 
Msg sent from client 

*****In client thread***** 
Msg received by client 
received: numResources requested = 9001 
sending: numResources requested = 9002 
Msg sent from client 


*****In server thread***** 
Msg received by server 
received: numResources requested = 0 
sending: numResources requested = 9001 
Msg sent from server. 


*****In client thread***** 
Msg received by client 
received: numResources requested = 9002 
sending: numResources requested = 9003 
Msg sent from client 


*****In server thread***** 
Msg received by server 
received: numResources requested = 9001 
sending: numResources requested = 9001 
Msg sent from server. 


*****In client thread***** 
Msg received by client 
received: numResources requested = 9003 
sending: numResources requested = 9004 
Msg sent from client 


*****In server thread***** 
Msg received by server 
received: numResources requested = 9001 
sending: numResources requested = 9001 
Msg sent from server. 

这些都没有在这两者之间的代码所做的更改运行后,其他1。

+0

我再次运行它,它在前几个循环中给了我非常奇怪的数字,但后来解决了第一次迭代中似乎正在工作的结果。不知道.... 编辑:运行它第四次,它给我第二次运行的结果。我看到一种模式... – Anon 2010-11-15 02:21:30

2

你的问题是你已经在消息队列上设置了无意义的权限。在这些线路,你已经使用十进制常量666,你应该用一个八进制常数0666

msqid1 = msgget(key1, 666 | IPC_CREAT); 
    msqid1 = msgget(key1, 666 | IPC_CREAT); 

这意味着,您所创建的队列,八进制权限,不包括读权限 - 所以你的后续msgget()调用现在都失败EPERM(你会看到,如果你检查这些呼叫的错误)。

您必须删除消息队列,并允许程序使用正确的权限重新创建消息队列。你需要与IPC_RMID命令使用msqid的队列msgctl()要做到这一点,如下面的程序:

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/msg.h> 

int main(int argc, char *argv[]) 
{ 
     if (argc < 2) { 
       fprintf(stderr, "Usage: %s <msqid> [<msgqid> ...]\n", argv[0]); 
       return 1; 
     } 

     while (*++argv) 
     { 
       int msqid = atoi(*argv); 

       printf("Removing msqid %d\n", msqid); 
       if (msgctl(msqid, IPC_RMID, NULL) != 0) { 
         perror("msgctl"); 
         return 2; 
       } 
     } 

     return 0; 
} 

由于SYS V消息队列的可怕的设计,你不能得到msqid因为msgget()失败,所以从msgget()开始的值。要获取要删除的msqid值,请查看文件/proc/sysvipc/msg

PS:

强烈建议使用POSIX消息队列代替(mq_open()mq_send()mq_receive()等)。界面显着改善。