具有 FIFO 管道的分段错误(核心转储)以及服务器和客户端之间的分叉通信
Segmentation fault (core dumped) with FIFO pipes and fork communication between server and client
我正在编写一个项目,您可以在一个终端中启动服务器,而在作为客户端的其他终端中,您可以使用 FIFO 管道将消息从一个用户发送到另一个用户。服务器创建从客户端读取消息的 FIFO 管道。客户端创建 FIFO 管道以从服务器读取消息。
在一个启动服务器的终端中,我键入 ./projectname --start
,在客户端中,我键入 ./projectname --login nickname
。当我关闭客户端时,我的服务器收到分段错误(核心转储)错误消息。在 x 小时内,我试图以我所知道的一切可能的方式摆脱它。如何修复?
我也曾尝试使用 void verifyloginclient(char *login)
函数注册用户,但父进程无法从子进程接收信息并陷入无限状态 while(1)
向服务器发送一些消息,这也使服务器因分段错误而崩溃,因此它被评论现在。
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
char userlist[10][30];
int succesfulllogin = 1;
void handler(int signum){
pid_t pid;
pid = wait(NULL);
succesfulllogin = 0;
printf("Parent knows child %d finished\n", (int)pid);
printf("Parent ending...\n");
}
void sig_handler_parent(int signum){
printf("signal response from child!\n");
succesfulllogin = 0;
exit(0);
}
void sig_handler_child(int signum){
printf("signal from parent\n");
succesfulllogin = 0;
exit(0);
}
void verifyloginclient(char *login)
{
int fd;
char buf[256];
char buf2[256];
snprintf(buf, sizeof buf, "%s%s", "fifopipes/","serwer.fifo");
if((fd = open(buf, O_WRONLY)) == -1){
perror("openFdloginclient");
exit(EXIT_FAILURE);
}
snprintf(buf2, sizeof buf2, "%s%s%s", login, " /login ",login);
if((write(fd, buf2, strlen(buf2))) == -1){
perror("writeloginclient");
}
close(fd);
}
int verifyloginserwer(char *login)
{
// check if login is on the userlist
int flagcmp = -1;
int x;
int indeks=0;
for(int i=0;i<10;i++){
x = strcmp(&userlist[i][0],login);
if(x==0){
flagcmp = i;
}
}
if(flagcmp == -1){ //if it doesnt exist we add him to first free slot
for(int i=0;i<10;i++){
if(userlist[i][0]=='[=10=]'){
strcpy(userlist[i],login);
printf("userlist: %s\n", userlist[i]);
succesfulllogin = 1;
break;
}
else{
indeks++;
}
}
}
else if(flagcmp != -1 || indeks==10){
fprintf(stderr, "loggin error!\n");
succesfulllogin = 0;
return 2;
}
return 0;
}
int splitstring(char *source, int desiredlength, char **s1,char **s2)
{
int len;
len = strlen(source);
if (desiredlength > len)
return(0);
*s1 = (char *) malloc(sizeof(char) * desiredlength);
*s2 = (char *) malloc(sizeof(char) * len-desiredlength+1);
if(s1 ==NULL || s2 == NULL)
return 0;
strncpy(*s1,source,desiredlength);
strncpy(*s2,source+desiredlength, len-desiredlength);
return(1);
}
void startserwer()
{
int fdserwer;
int fdanuluj;
int fd;
char readbuf[80];
int read_bytes;
char buf[256]; //pipe server
char buf2[256]; //pipe client
char buf3[256]; // message to client
for(int i=0;i<10;i++){ // declare userlist
userlist[i][0] = '[=10=]';
}
snprintf(buf, sizeof buf, "%s%s", "fifopipes/","serwer.fifo");
umask(0);
if(mkfifo(buf, 0777) == -1){
perror("mkfifoserwer");
exit(EXIT_FAILURE);
}
while(1){
if((fdserwer = open(buf, O_CREAT | O_RDONLY))== -1){
perror("openFdserwer");
exit(EXIT_FAILURE);
}
if((read_bytes = read(fdserwer, &readbuf, sizeof(readbuf)))== -1){
perror("readbytes");
}
else{
readbuf[read_bytes] = '[=10=]';
//SENDER LOGIN
char senderlogin[80];
strcpy(senderlogin, readbuf);
char *token = strtok(senderlogin, " ");
printf("%s\n", token);
strcpy(senderlogin, token);
int b;
char *loginnadawcy;
char *resztakomendy;
b = splitstring(readbuf, (int) strlen(token)+1,&loginnadawcy,&resztakomendy);
if(b!=1){
printf("error in command\n");
}
else{
loginnadawcy[strlen(token)]='[=10=]';
//COMMAND NAME AFTER SLASH /
char command[80];
strcpy(command, readbuf);
token = strtok(NULL, " ");
printf("%s\n",token);
strcpy(command, token);
int a;
char *komenda;
char *reszta;
a = splitstring(resztakomendy, (int)strlen(token)+1,&komenda,&reszta);
if(a!=1){
printf("error\n");
}
else{
komenda[strlen(token)]='[=10=]';
if(strcmp(komenda,"/login")==0){
if(verifyloginserwer(senderlogin)==2){
//open client pipe
snprintf(buf2, sizeof buf2, "%s%s%s", "fifopipes/",senderlogin,".fifo");
if((fdanuluj = open(buf2, O_WRONLY)) == -1){
perror("openFdanuluj");
exit(EXIT_FAILURE);
}
//SEND MESSAGE TO CLIENT
snprintf(buf3, sizeof buf3, "%s%s", "serwer ", "end");
if((write(fdanuluj, buf3, strlen(buf3))) == -1){
perror("writeFdanuluj");
}
close(fdanuluj);
}
}
else if(strcmp(komenda,"/w")==0){
//RECEIVER LOGIN
char receiverlogin[80];
token = strtok(NULL, " ");
printf("%s\n",token);
strcpy(receiverlogin, token);
int r;
char *login;
char *message;
r = splitstring(reszta,(int)strlen(token)+1,&login,&message);
if(r!=1){
printf("error\n");
}
else{
//RECEIVE INFORMATION
login[strlen(receiverlogin)]='[=10=]';
printf("from %s to %s: %s and length is %d \n", senderlogin, login, message, (int)strlen(message));
//OPEN CLIENT PIPE
snprintf(buf2, sizeof buf2, "%s%s%s", "fifopipes/",receiverlogin,".fifo");
if((fd = open(buf2, O_WRONLY))== -1){
perror("openFd");
exit(EXIT_FAILURE);
}
//SEND MESSAGE TO CLIENT
snprintf(buf3, sizeof buf3, "%s%s%s", senderlogin," ",message);
if( (write(fd, buf3, strlen(buf3) )) == -1){
perror("writeopenfd");
}
close(fd);
}
}
}
}
}
close(fdserwer);
}
unlink(buf);
}
void clientchild(char *login)
{
int fd;
char readbuf[80];
int read_bytes;
char buf[256];
snprintf(buf, sizeof buf, "%s%s%s", "fifopipes/",login,".fifo");
umask(0);
if(mkfifo(buf, 0777) == -1){
perror("mkfifoclient");
exit(EXIT_FAILURE);
}
while(1){
if((fd = open(buf, O_CREAT | O_RDONLY)) == -1){
perror("openFdchild");
exit(EXIT_FAILURE);
}
if((read_bytes = read(fd, &readbuf, sizeof(readbuf))) == -1){
perror("readfdchild");
}
else{
readbuf[read_bytes] = '[=10=]';
//SENDER LOGIN
char nickname[80];
strcpy(nickname, readbuf);
char * token = strtok(nickname, " ");
//printf("%s\n",token);
int r;
char *login;
char *message;
r = splitstring(readbuf,(int)strlen(token)+1,&login,&message);
if(r!=1){
printf("blad\n");
}
else{
login[strlen(token)]='[=10=]';
if(strcmp(login,"serwer")==0 && strcmp(message,"end")==0){
printf("Login error. Closing...\n");
close(fd);
break;
}
printf("%s: %s and length is %d \n", login, message, (int)strlen(message));
close(fd);
//printf("Received string: \"%s\" and length is %d \n", readbuf, (int)strlen(readbuf));
}
//free(login);
//free(message);
}
}
unlink(buf);
}
void clientparent(char *login)
{
signal(SIGQUIT,sig_handler_parent);
int fd;
int stringlen;
char readbuf[80];
char buf[256];
char buf2[256];
snprintf(buf, sizeof buf, "%s%s", "fifopipes/","serwer.fifo");
printf("FIFO_CLIENT: Send messages infinitely\n");
while(1){
if((fd = open(buf, O_WRONLY)) == -1){
perror("openFdparent");
exit(EXIT_FAILURE);
}
//printf("Enter string: ");
fgets(readbuf, sizeof(readbuf), stdin);
stringlen = strlen(readbuf);
readbuf[stringlen - 1] = '[=10=]';
snprintf(buf2, sizeof buf2, "%s%s%s", login," ",readbuf);
if(strlen(login)+1 == strlen(buf2)){
printf("Error\n");
break;
}
else{
if((write(fd, buf2, strlen(buf2))) == -1){
perror("writeparent");
}
printf("Sent string: \"%s\" and string length is %d \n", buf2, (int)strlen(buf2));
}
}
close(fd);
}
void splitclient(char *login)
{
printf("login: %s\n", login);
pid_t pid = fork();
printf("fork returned: %d\n", (int) pid);
//signal(SIGCHLD, handler);
if (pid < 0){
perror("Fork failed");
}
else if (pid == 0){
signal(SIGQUIT,sig_handler_child);
printf("I am the child with pid %d\n", (int) getpid());
char buf[256];
snprintf(buf, sizeof buf, "%s%d", "Child ",(int) getpid());
//kod dziecka
clientchild(login);
//kill(getppid(),SIGQUIT);
exit(0);
}
else{
// We must be the parent
printf("I am the parent, waiting for child to end \n");
//kod rodzica
clientparent(login);
pid_t childpid = wait(NULL);
printf("Parent knows child %d finished\n", (int)childpid);
printf("Parent ending...\n");
}
}
int main(int argc, char **argv)
{
while(1)
{
int c;
int option_index = 0;
static struct option long_options[] =
{
{"start", no_argument, NULL, 's'},
{"login", required_argument, NULL, 'l'},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "sl:", long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 's':
printf("start server\n");
startserwer();
break;
case 'l':
printf("login with option %s \n", optarg);
//verifyloginclient(optarg);
splitclient(optarg);
break;
case '?':
break;
default:
abort();
}
}
if (optind < argc)
{
printf("non-option ARGV-elements: ");
while (optind < argc)
printf("%s ", argv[optind++]);
putchar ('\n');
}
return 0;
}
来自startServer()
中的代码:
if((read_bytes = read(fdserwer, &readbuf, sizeof(readbuf)))== -1){
perror("readbytes");
}
else{
:
char *token = strtok(senderlogin, " ");
:
strcpy(senderlogin, token);
b = splitstring(readbuf, (int)
strlen(token)+1,&loginnadawcy,&resztakomendy);
您没有验证 token
是否是非 NULL
指针 post 标记化。在 child 退出的情况下,read()
将 return 为 0(而不是 -1 作为失败),表明 EOF 正如 man 告诉的那样:
RETURN VALUE
On success, the number of bytes read is returned (zero indicates
end of file),
因此 senderlogin
缓冲区将是空的并且不会产生任何标记。您需要考虑这种情况并进行适当的空值检查。添加空 chek 将导致服务器程序正常退出。
我正在编写一个项目,您可以在一个终端中启动服务器,而在作为客户端的其他终端中,您可以使用 FIFO 管道将消息从一个用户发送到另一个用户。服务器创建从客户端读取消息的 FIFO 管道。客户端创建 FIFO 管道以从服务器读取消息。
在一个启动服务器的终端中,我键入 ./projectname --start
,在客户端中,我键入 ./projectname --login nickname
。当我关闭客户端时,我的服务器收到分段错误(核心转储)错误消息。在 x 小时内,我试图以我所知道的一切可能的方式摆脱它。如何修复?
我也曾尝试使用 void verifyloginclient(char *login)
函数注册用户,但父进程无法从子进程接收信息并陷入无限状态 while(1)
向服务器发送一些消息,这也使服务器因分段错误而崩溃,因此它被评论现在。
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
char userlist[10][30];
int succesfulllogin = 1;
void handler(int signum){
pid_t pid;
pid = wait(NULL);
succesfulllogin = 0;
printf("Parent knows child %d finished\n", (int)pid);
printf("Parent ending...\n");
}
void sig_handler_parent(int signum){
printf("signal response from child!\n");
succesfulllogin = 0;
exit(0);
}
void sig_handler_child(int signum){
printf("signal from parent\n");
succesfulllogin = 0;
exit(0);
}
void verifyloginclient(char *login)
{
int fd;
char buf[256];
char buf2[256];
snprintf(buf, sizeof buf, "%s%s", "fifopipes/","serwer.fifo");
if((fd = open(buf, O_WRONLY)) == -1){
perror("openFdloginclient");
exit(EXIT_FAILURE);
}
snprintf(buf2, sizeof buf2, "%s%s%s", login, " /login ",login);
if((write(fd, buf2, strlen(buf2))) == -1){
perror("writeloginclient");
}
close(fd);
}
int verifyloginserwer(char *login)
{
// check if login is on the userlist
int flagcmp = -1;
int x;
int indeks=0;
for(int i=0;i<10;i++){
x = strcmp(&userlist[i][0],login);
if(x==0){
flagcmp = i;
}
}
if(flagcmp == -1){ //if it doesnt exist we add him to first free slot
for(int i=0;i<10;i++){
if(userlist[i][0]=='[=10=]'){
strcpy(userlist[i],login);
printf("userlist: %s\n", userlist[i]);
succesfulllogin = 1;
break;
}
else{
indeks++;
}
}
}
else if(flagcmp != -1 || indeks==10){
fprintf(stderr, "loggin error!\n");
succesfulllogin = 0;
return 2;
}
return 0;
}
int splitstring(char *source, int desiredlength, char **s1,char **s2)
{
int len;
len = strlen(source);
if (desiredlength > len)
return(0);
*s1 = (char *) malloc(sizeof(char) * desiredlength);
*s2 = (char *) malloc(sizeof(char) * len-desiredlength+1);
if(s1 ==NULL || s2 == NULL)
return 0;
strncpy(*s1,source,desiredlength);
strncpy(*s2,source+desiredlength, len-desiredlength);
return(1);
}
void startserwer()
{
int fdserwer;
int fdanuluj;
int fd;
char readbuf[80];
int read_bytes;
char buf[256]; //pipe server
char buf2[256]; //pipe client
char buf3[256]; // message to client
for(int i=0;i<10;i++){ // declare userlist
userlist[i][0] = '[=10=]';
}
snprintf(buf, sizeof buf, "%s%s", "fifopipes/","serwer.fifo");
umask(0);
if(mkfifo(buf, 0777) == -1){
perror("mkfifoserwer");
exit(EXIT_FAILURE);
}
while(1){
if((fdserwer = open(buf, O_CREAT | O_RDONLY))== -1){
perror("openFdserwer");
exit(EXIT_FAILURE);
}
if((read_bytes = read(fdserwer, &readbuf, sizeof(readbuf)))== -1){
perror("readbytes");
}
else{
readbuf[read_bytes] = '[=10=]';
//SENDER LOGIN
char senderlogin[80];
strcpy(senderlogin, readbuf);
char *token = strtok(senderlogin, " ");
printf("%s\n", token);
strcpy(senderlogin, token);
int b;
char *loginnadawcy;
char *resztakomendy;
b = splitstring(readbuf, (int) strlen(token)+1,&loginnadawcy,&resztakomendy);
if(b!=1){
printf("error in command\n");
}
else{
loginnadawcy[strlen(token)]='[=10=]';
//COMMAND NAME AFTER SLASH /
char command[80];
strcpy(command, readbuf);
token = strtok(NULL, " ");
printf("%s\n",token);
strcpy(command, token);
int a;
char *komenda;
char *reszta;
a = splitstring(resztakomendy, (int)strlen(token)+1,&komenda,&reszta);
if(a!=1){
printf("error\n");
}
else{
komenda[strlen(token)]='[=10=]';
if(strcmp(komenda,"/login")==0){
if(verifyloginserwer(senderlogin)==2){
//open client pipe
snprintf(buf2, sizeof buf2, "%s%s%s", "fifopipes/",senderlogin,".fifo");
if((fdanuluj = open(buf2, O_WRONLY)) == -1){
perror("openFdanuluj");
exit(EXIT_FAILURE);
}
//SEND MESSAGE TO CLIENT
snprintf(buf3, sizeof buf3, "%s%s", "serwer ", "end");
if((write(fdanuluj, buf3, strlen(buf3))) == -1){
perror("writeFdanuluj");
}
close(fdanuluj);
}
}
else if(strcmp(komenda,"/w")==0){
//RECEIVER LOGIN
char receiverlogin[80];
token = strtok(NULL, " ");
printf("%s\n",token);
strcpy(receiverlogin, token);
int r;
char *login;
char *message;
r = splitstring(reszta,(int)strlen(token)+1,&login,&message);
if(r!=1){
printf("error\n");
}
else{
//RECEIVE INFORMATION
login[strlen(receiverlogin)]='[=10=]';
printf("from %s to %s: %s and length is %d \n", senderlogin, login, message, (int)strlen(message));
//OPEN CLIENT PIPE
snprintf(buf2, sizeof buf2, "%s%s%s", "fifopipes/",receiverlogin,".fifo");
if((fd = open(buf2, O_WRONLY))== -1){
perror("openFd");
exit(EXIT_FAILURE);
}
//SEND MESSAGE TO CLIENT
snprintf(buf3, sizeof buf3, "%s%s%s", senderlogin," ",message);
if( (write(fd, buf3, strlen(buf3) )) == -1){
perror("writeopenfd");
}
close(fd);
}
}
}
}
}
close(fdserwer);
}
unlink(buf);
}
void clientchild(char *login)
{
int fd;
char readbuf[80];
int read_bytes;
char buf[256];
snprintf(buf, sizeof buf, "%s%s%s", "fifopipes/",login,".fifo");
umask(0);
if(mkfifo(buf, 0777) == -1){
perror("mkfifoclient");
exit(EXIT_FAILURE);
}
while(1){
if((fd = open(buf, O_CREAT | O_RDONLY)) == -1){
perror("openFdchild");
exit(EXIT_FAILURE);
}
if((read_bytes = read(fd, &readbuf, sizeof(readbuf))) == -1){
perror("readfdchild");
}
else{
readbuf[read_bytes] = '[=10=]';
//SENDER LOGIN
char nickname[80];
strcpy(nickname, readbuf);
char * token = strtok(nickname, " ");
//printf("%s\n",token);
int r;
char *login;
char *message;
r = splitstring(readbuf,(int)strlen(token)+1,&login,&message);
if(r!=1){
printf("blad\n");
}
else{
login[strlen(token)]='[=10=]';
if(strcmp(login,"serwer")==0 && strcmp(message,"end")==0){
printf("Login error. Closing...\n");
close(fd);
break;
}
printf("%s: %s and length is %d \n", login, message, (int)strlen(message));
close(fd);
//printf("Received string: \"%s\" and length is %d \n", readbuf, (int)strlen(readbuf));
}
//free(login);
//free(message);
}
}
unlink(buf);
}
void clientparent(char *login)
{
signal(SIGQUIT,sig_handler_parent);
int fd;
int stringlen;
char readbuf[80];
char buf[256];
char buf2[256];
snprintf(buf, sizeof buf, "%s%s", "fifopipes/","serwer.fifo");
printf("FIFO_CLIENT: Send messages infinitely\n");
while(1){
if((fd = open(buf, O_WRONLY)) == -1){
perror("openFdparent");
exit(EXIT_FAILURE);
}
//printf("Enter string: ");
fgets(readbuf, sizeof(readbuf), stdin);
stringlen = strlen(readbuf);
readbuf[stringlen - 1] = '[=10=]';
snprintf(buf2, sizeof buf2, "%s%s%s", login," ",readbuf);
if(strlen(login)+1 == strlen(buf2)){
printf("Error\n");
break;
}
else{
if((write(fd, buf2, strlen(buf2))) == -1){
perror("writeparent");
}
printf("Sent string: \"%s\" and string length is %d \n", buf2, (int)strlen(buf2));
}
}
close(fd);
}
void splitclient(char *login)
{
printf("login: %s\n", login);
pid_t pid = fork();
printf("fork returned: %d\n", (int) pid);
//signal(SIGCHLD, handler);
if (pid < 0){
perror("Fork failed");
}
else if (pid == 0){
signal(SIGQUIT,sig_handler_child);
printf("I am the child with pid %d\n", (int) getpid());
char buf[256];
snprintf(buf, sizeof buf, "%s%d", "Child ",(int) getpid());
//kod dziecka
clientchild(login);
//kill(getppid(),SIGQUIT);
exit(0);
}
else{
// We must be the parent
printf("I am the parent, waiting for child to end \n");
//kod rodzica
clientparent(login);
pid_t childpid = wait(NULL);
printf("Parent knows child %d finished\n", (int)childpid);
printf("Parent ending...\n");
}
}
int main(int argc, char **argv)
{
while(1)
{
int c;
int option_index = 0;
static struct option long_options[] =
{
{"start", no_argument, NULL, 's'},
{"login", required_argument, NULL, 'l'},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "sl:", long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 's':
printf("start server\n");
startserwer();
break;
case 'l':
printf("login with option %s \n", optarg);
//verifyloginclient(optarg);
splitclient(optarg);
break;
case '?':
break;
default:
abort();
}
}
if (optind < argc)
{
printf("non-option ARGV-elements: ");
while (optind < argc)
printf("%s ", argv[optind++]);
putchar ('\n');
}
return 0;
}
来自startServer()
中的代码:
if((read_bytes = read(fdserwer, &readbuf, sizeof(readbuf)))== -1){
perror("readbytes");
}
else{
:
char *token = strtok(senderlogin, " ");
:
strcpy(senderlogin, token);
b = splitstring(readbuf, (int)
strlen(token)+1,&loginnadawcy,&resztakomendy);
您没有验证 token
是否是非 NULL
指针 post 标记化。在 child 退出的情况下,read()
将 return 为 0(而不是 -1 作为失败),表明 EOF 正如 man 告诉的那样:
RETURN VALUE
On success, the number of bytes read is returned (zero indicates end of file),
因此 senderlogin
缓冲区将是空的并且不会产生任何标记。您需要考虑这种情况并进行适当的空值检查。添加空 chek 将导致服务器程序正常退出。