【发布时间】:2022-01-03 00:41:50
【问题描述】:
我在写一个项目,里面有两个程序,客户端和服务端,客户端向服务端发送一个字符串,服务端处理后返回给客户端(可以同时有多个客户端,这就是我的问题所在)。我在需要处理的相同字符串中从客户端发送进程 ID,服务器提取进程 ID。但是我得到了随机的核心转储,这些转储不一致。大多数时候它工作正常。它发生在调用strtol() 调用receive_message(...) 函数之前。
服务器receive_message(...)函数:
int receive_message(struct message *x){
int ret_val, z;
ret_val = msgrcv(msg_q_id, x, MAX, 0, 0);
if (ret_val == -1){
if (signal_detection == 1){
exit(0);
}
perror("COULDNT receive a message!");
exit(-1);
} else {
int c = 0;
while (x->mtext[c] != '!'){
++c;
}
int h = c;
char tab[strlen(x -> mtext) - c];
int s = 0;
for (int counter = c + 1; counter < strlen(x->mtext); ++counter){
tab[s++] = x->mtext[counter];
}
printf("\n%s\n", tab);
z = strtol(tab, NULL, 10);
memset((x -> mtext) + h, 0, strlen(x -> mtext) - 1 - c);
printf("message received: %s\n", x -> mtext);
}
return z;
}
整个服务器代码:
#include <errno.h>
#include <ctype.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <signal.h>
#define MAX 255
#define CLIENT 1
#define SERVER 2
int signal_detection = 0;
int msg_q_id;
key_t msg_q_key;
struct message;
void create_queue();
void send_message(struct message *x, int pid);
int receive_message(struct message *x);
void delete_message_q();
void to_upper_case(struct message *x);
void signal_handler(int signum, siginfo_t *info, void *ptr);
struct message{
long int mtype;
char mtext[MAX];
};
int main(){
struct message member_of_message;
struct message *ptr;
struct sigaction sig;
int sig_ret;
ptr = &member_of_message;
sig.sa_sigaction = signal_handler;
sig_ret = sigaction(SIGINT, &sig, NULL);
if (sig_ret == -1){
perror("sigaction fail");
}
create_queue();
while (1){
int pid;
memset(member_of_message.mtext, 0, strlen(member_of_message.mtext));
printf("waiting for message\n");
pid = receive_message(ptr);
to_upper_case(ptr);
printf("After uppering: %s\n", member_of_message.mtext);
send_message(ptr, pid);
sleep(1);
}
}
void create_queue(){
printf("starting to create queue\n");
msg_q_key = ftok(",", 4);
msg_q_id = msgget(msg_q_key, 0700|IPC_CREAT);
if (msg_q_id == -1){
perror("COULDNT create msgq");
exit(-1);
} else {
printf("succesfully created: %d !\n", msg_q_id);
}
}
void send_message(struct message *x, int pid){
int ret_val;
x -> mtype = pid + 1;
wysylanie:
ret_val = msgsnd(msg_q_id, x, strlen(x -> mtext) + 1, 0);
if (ret_val == -1){
if (errno == EAGAIN){
perror("message queue is full!");
goto wysylanie;
}
perror("COULDNT send a message");
exit(-1);
} else {
printf("message sent!\n");
}
}
int receive_message(struct message *x){
int ret_val, z;
ret_val = msgrcv(msg_q_id, x, MAX, 0, 0);
if (ret_val == -1){
if (signal_detection == 1){
exit(0);
}
perror("COULDNT receive a message!");
exit(-1);
} else {
int c = 0;
while (x->mtext[c] != '!'){
++c;
}
int h = c;
char tab[strlen(x -> mtext) - c];
int s = 0;
for (int counter = c + 1; counter < strlen(x->mtext) - 1; ++counter){
tab[s++] = x->mtext[counter];
}
printf("\n%s\n", tab);
z = strtol(tab, NULL, 10);
memset((x -> mtext) + h, 0, strlen(x -> mtext) - 1 - c);
printf("message received: %s\n", x -> mtext);
}
return z;
}
void delete_message_q(){
int ret_val;
ret_val = msgctl(msg_q_id, IPC_RMID, 0);
if (ret_val == -1){
perror("COULDNT remove message queue");
exit(-1);
} else {
printf("message queue deleted!\n");
}
}
void to_upper_case(struct message *x){
for (int counter = 0; counter < strlen(x->mtext); ++counter){
x->mtext[counter] = toupper(x->mtext[counter]);
}
}
void signal_handler(int signum, siginfo_t *info, void *ptr){
signal_detection = 1;
printf("\nReceived a signal!\nstopping iteration\n");
delete_message_q();
}
客户端代码:
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <pthread.h>
#include <string.h>
#define MAX 255
#define CLIENT 1
#define SERVER 2
#define M_SENT 3
int msg_q_id;
key_t msg_q_key;
struct message;
int pid;
void create_queue();
void *send_message();
void *receive_message(void *arg);
struct message{
long int mtype;
char mtext[MAX];
};
int main(){
struct message member_of_message;
struct message *ptr;
int thread_val;
ptr = &member_of_message;
pthread_t pid1, pid2;
create_queue();
sleep(1);
printf("creating thread1......\n");
thread_val = pthread_create(&pid1, NULL, send_message, NULL);
if (thread_val != 0){
perror("couldnt create thread");
exit(-1);
}
printf("creating thread2......\n");
thread_val = pthread_create(&pid2, NULL, receive_message, ptr);
if (thread_val != 0){
perror("couldnt create thread");
exit(-1);
}
thread_val = pthread_join(pid1, NULL);
if (thread_val != 0){
perror("couldnt create thread");
exit(-1);
}
thread_val = pthread_join(pid2, NULL);
if (thread_val != 0){
perror("couldnt create thread");
exit(-1);
}
}
void create_queue(){
printf("starting creation of a queue\n");
msg_q_key = ftok(",", 4);
msg_q_id = msgget(msg_q_key, 0700|IPC_CREAT);
if (msg_q_id == -1){
perror("COULDNT create msgq");
exit(-1);
} else {
printf("succesfully created: %d !\n", msg_q_id);
}
}
void *send_message(){
int last_val;
struct message member_of_message;
int ret_val;
char rub[10000];
for (int message_counter = 0; message_counter < M_SENT; ++message_counter){
pid = getpid();
member_of_message.mtype = pid;
char arr[MAX];
if (fgets(arr, MAX - 20, stdin) == NULL){
perror("not a single char read, message sent is empty");
}
if (strlen(arr) == 1){
perror("cannot send empty message!");
exit(-1);
}
if (strchr(arr, '\n') == NULL){
perror("Przepelniono komunikat!");
fgets(rub, 10000, stdin);
}
char temp_arr[20];
int sp_retval;
sp_retval = sprintf(temp_arr, "%d", pid);
if (sp_retval == 0){
perror("0 bytes read");
exit(-1);
}
for (int counter = 0; counter < strlen(arr) - 1; ++counter){
member_of_message.mtext[counter] = arr[counter];
last_val = counter;
}
member_of_message.mtext[last_val + 1] = '!';
strcat(member_of_message.mtext, temp_arr);
wysylanie:
ret_val = msgsnd(msg_q_id, (struct message*)&member_of_message, strlen(member_of_message.mtext), 0);
if (ret_val == -1){
if (errno == EAGAIN){
perror("message queue is full!");
goto wysylanie;
}
perror("COULDNT send a message");
exit(-1);
} else {
printf("message sent!, PID: %d \n", pid);
memset(member_of_message.mtext, 0, strlen(member_of_message.mtext));
}
}
}
void *receive_message(void *arg){
int ret_val;
for (int message_counter = 0; message_counter < M_SENT; ++message_counter){
sleep(1);
((struct message*)arg)->mtype = pid + 1;
ret_val = msgrcv(msg_q_id, (struct message*)arg, MAX, ((struct message*)arg)->mtype, 0);
if (ret_val == -1){
perror("COULDNT receive a message!");
exit(-1);
} else {
printf("message received: %s\n", ((struct message*)arg)->mtext);
memset(((struct message*)arg)->mtext, 0, strlen(((struct message*)arg)->mtext));
}
}
}
【问题讨论】:
-
是否缺少
tab[s] = '\0'? -
@KamilCuk 试过了,核心转储仍然存在;/
-
这一行:
ret_val = msgsnd(msg_q_id, (struct message*)&member_of_message, strlen(member_of_$无法编译。剪切/粘贴代码时请使用换行。 -
@EmployedRussian 对,我编辑了,谢谢指出!
-
无论如何,用
-Wall -Wextra -fsanitize=undefined,address -g3编译并等待错误。它很可能会解决大多数问题。
标签: c linux gcc struct message-queue