этот код реализует простую систему связи клиент-сервер с использованием очередей сообщений на языке C.
local.h
#include <stdio.h>
#include <sys/types.h>
#include "sys/ipc.h"
#include <sys/msg.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#define SEED 'g' /* seed for ftok */
#define SERVER 1L /* message for the server */
typedef struct{
long msg_to; /* placed in the queue for */
long msg_fm; /* placed in the queue by */
char buffer[BUFSIZ];
}MESSAGE;
клиент.с:
#include "local.h"
int main(int argc, char const *argv[])
{
key_t key;
pid_t cli_pid;
int mid, n;
MESSAGE msg;
static char m_key[10];
cli_pid = getpid();
if ((key = ftok(".", SEED)) == -1){
perror("Client: key generation");
exit(1);
}
if ((mid = msgget(key, 0)) == -1){
mid = msgget(key, IPC_CREAT | 0660);
printf("%d", mid);
switch (fork()){
case -1:
perror("Client: fork");
exit(3);
case 0:
sprintf(m_key, "%d", mid);
execlp("./server", "server", m_key, NULL);
perror("Client: exec");
exit(4);
}
}
while(1){
msg.msg_to = SERVER;
msg.msg_fm = cli_pid;
write(fileno(stdout), "cmd>", 5);
memset(msg.buffer, 0x0, BUFSIZ);
n = read(fileno(stdin), msg.buffer, BUFSIZ);
if (n == 0){
break;
}
if (msgsnd(mid, &msg, sizeof(msg), 0) == -1){
perror("Client: msgsend");
exit(5);
}
if ((n = msgrcv(mid, &msg, sizeof(msg), cli_pid, 0)) != -1){
write(fileno(stdout), msg.buffer, strlen(msg.buffer));
}
}
msgsnd(mid, &msg, 0, 0);
exit(0);
}
сервер.с:
#include "local.h"
int main(int argc, char const *argv[])
{
int mid, n;
MESSAGE msg;
void process_msg(char *, int);
if (argc != 3) {
fprintf(stderr, "Usage: %s msq_id &\n", argv[0]);
exit(1);
}
while (1) {
if ((n=msgrcv(mid, &msg, sizeof(msg), SERVER, 0)) == -1 ) {
perror("Server: msgrcv");
exit(2);
} else if (n == 0){
break;
} else {
process_msg(msg.buffer, strlen(msg.buffer));
msg.msg_to = msg.msg_fm;
msg.msg_fm = SERVER;
if (msgsnd(mid, &msg, sizeof(msg), 0) == -1 ) {
perror("Server: msgsnd");
exit(3);
}
}
}
msgctl(mid, IPC_RMID, (struct msqid_ds *) 0 );
exit(0);
}
void process_msg(char *b, int len) {
int i;
for (i = 0; i < len; ++i){
if (isalpha(*(b + i))){
*(b + i) = toupper(*(b + i));
}
}
}
Если я попытаюсь скомпилировать эти файлы с помощью этих команд:
gcc -o сервер server.c
gcc -o клиент client.c
и запустите файлы:
./сервер 123 &
./клиент
Сервер запущен и ждет,
(базовый) user@PC:~/UNIX/mqueues$ ./server 123 &
[2] 93463
(базовый) user@PC:~/UNIX/mqueues$ Использование: ./server msq_id &
/жду сообщения здесь/
затем я пытаюсь отправить сообщение от клиента. Однако я получаю это сообщение об ошибке от клиента:
(базовый) user@PC:~/UNIX/mqueues$ ./client
cmd>привет
Клиент: msgsend: неверный аргумент
Наверное я что-то делаю не так, буду очень признателен, если вы мне поможете. Спасибо.
Где server.c инициализирует mid?
Можете ли вы добавить в client.c код, который выполняет perror, если mid = msgget(key, IPC_CREAT | 0660); равно -1?
Я перепробовал все предложения здесь, но все равно. Я получаю ту же ошибку «Неверный аргумент». Спасибо за ваш ответ.





в строках кода ниже для msg_to не установлено значение SERVER. Кажется, это проблема.
process_msg(msg.buffer, strlen(msg.buffer));
msg.msg_to = msg.msg_fm;
msg.msg_fm = SERVER;
Если msg_to не установлен, msg_type недействителен для вызова msgsend() и может произойти сбой.
Спасибо за ваш ответ, однако он все тот же.
БУФСИЗ нигде не устанавливается. Или это пропущено при копировании кода? Можно ли использовать жестко закодированное сообщение, а не стандартный ввод, чтобы проверить, в чем проблема.
BUFSIZ нигде не установлен, вы правы. Потому что это происходит из-под stdio.h. Также я попробовал жестко закодированное сообщение, однако получаю то же сообщение об ошибке.
BUFSIZ имеет размер 8 КБ. Пожалуйста, проверьте максимальный размер сообщения, которое можно использовать при вызове msgsend(). Я считаю, что это также 8k. на данный момент просто проверяйте с помощью 20 байтов или небольшого размера буфера вместо BUFSIZ на случай, если мы сможем сузить эту проблему
Видеть:
(base) user@PC:~/UNIX/mqueues$ ./server 123 &
[2] 93463
(base) user@PC:~/UNIX/mqueues$ Usage: ./server msq_id &
/waiting for message here/
Это означает, что сервер вышел из строя (сообщение usage...).
Первая ошибка заключается в том, что вам необходимо передать на сервер 3 аргумента, но последний & не является частью аргументов команды, а используется оболочкой для запуска команды в фоновом режиме.
Вторая ошибка заключается в том, что вы должны сначала создать очередь сообщений на сервере, прежде чем вызывать msgrcv. Если нет, то как сервер сможет что-то прочитать?
В-третьих, какая логика стоит за всем этим? Клиент разветвляет сервер, но кажется, что вы тоже хотите запустить сервер вручную. Забудьте о запуске сервера с клиента.
Я заметил одну проблему: вы передаете
sizeof(MESSAGE)в качестве размера сообщения, но размер не должен включать частьmtype(в вашем случае частьmsg_to), поэтому между процессами копируются случайные байты. Насколько я понимаю, это не имеет отношения к вашей проблеме. Но просто чтобы вы знали.