У меня проблема с домашней работой. Socket-программирование с доменом Unix
1. Клиент отправить имя файла на сервер
2. Сервер проверяет наличие файла, открывает и посылает дескриптор файла клиенту
3. Клиент открывает дескриптор файла и выводит на экран. platform = ubuntu 12.04. У меня проблема с клиентом. Неисправность Сегментация Error (ядро сбрасывали) на линии fd = *p
(я пометили на коде клиента)
это мой кодОшибка сегментации при программировании гнезда
Сервер
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdbool.h>
#include <signal.h>
#include <sys/wait.h>
#define SOCKNAME "sockunix"
bool ende = false;
void sigfkt(int signr){
printf("SIGINT empfangen ...\n");
ende = true;
}
int main(){
int fd, sockd, sockd2, rc, *p, sl;
FILE *fp;
struct sockaddr_un uxadr;
struct msghdr mh;
struct cmsghdr *cmp;
char ctrl[sizeof(struct cmsghdr)+10];
struct iovec iov[1];
char eab[100];
//bat dau khai bao
mh.msg_name = NULL;
mh.msg_namelen = 0;
mh.msg_iov = iov;
mh.msg_iovlen = 1;
mh.msg_control = ctrl;
mh.msg_controllen = sizeof(ctrl);
mh.msg_flags = 0;
cmp = CMSG_FIRSTHDR(&mh);
cmp->cmsg_len = CMSG_LEN(fd);
cmp->cmsg_level = SOL_SOCKET;
cmp->cmsg_type = SCM_RIGHTS;
p = (int *)CMSG_DATA(cmp);
// khoi tao socket
uxadr.sun_family = AF_UNIX;
strcpy(uxadr.sun_path, SOCKNAME);
sockd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sockd<0){
perror("socket");
exit(1);
}
unlink(uxadr.sun_path);
sl = sizeof(uxadr);
rc = bind(sockd, (struct sockaddr*)&uxadr, sl);
if(rc<0){
perror("bind");
exit(2);
}
rc = listen(sockd, 10);
if(rc<0){
perror("listen");
exit(3);
}
sigset(SIGINT, sigfkt);
printf("Warte auf Client-Anforderungen ....\n"); //cho client ket noi toi
do{
sockd2 = accept(sockd, 0, 0);
if(ende)
break;
if(sockd2<0){
perror("accept");
exit(4);
}
iov[0].iov_base = eab;
iov[0].iov_len = sizeof(eab);
rc = recvmsg(sockd2,&mh,0); //nhan File name tu client
if(rc<0){
perror("recvmsg");
exit(5);
}
printf("%s\n",eab);
if(rc>0){
fp = fopen(eab,"r");// kiem tra xem file ton tai ko?
if(fp==NULL){
printf("file not existiert\n");
eab[0]=1; // thong bao cho client file ko ton tai
}
else{
fd = fileno(fp); // lay File descriptor
eab[0]=2; // thong bao cho client file ton tai
*p = fd; //gan File descriptor vao cau truc dieu khien
}
}
printf("fd=%d\n",*p);
rc = sendmsg(sockd2,&mh,0); // guoi thong bao va File descriptor den client
if(rc<0){
perror("sendmsg");
}
close(sockd2);
}while(!ende);
close(sockd);
unlink(uxadr.sun_path);
}
Client
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdbool.h>
#include <signal.h>
#include <sys/wait.h>
#define SOCKNAME "sockunix"
int main(int argc, char *argv[]){
int fd = 0, sockd, rc, *p, sl;
FILE *fp;
struct sockaddr_un uxadr;
struct msghdr mh;
struct cmsghdr *cmp;
char ctrl[sizeof(struct cmsghdr)+10];
struct iovec iov[1];
char eab[100],fname[100];
//bat dau khai bao
mh.msg_name = NULL;
mh.msg_namelen = 0;
mh.msg_iov = iov;
mh.msg_iovlen = 1;
mh.msg_control = ctrl;
mh.msg_controllen = sizeof(ctrl);
mh.msg_flags = 0;
cmp = CMSG_FIRSTHDR(&mh);
cmp->cmsg_len = CMSG_LEN(fd);
cmp->cmsg_level = SOL_SOCKET;
cmp->cmsg_type = SCM_RIGHTS;
p = (int *)CMSG_DATA(cmp);
//khoi tao socket
uxadr.sun_family = AF_UNIX;
strcpy(uxadr.sun_path, SOCKNAME);
sockd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sockd<0){
perror("socket");
exit(1);
}
sl = sizeof(uxadr);
rc = connect(sockd, (struct sockaddr *)&uxadr, sl);
if(rc<0){
perror("connect");
exit(2);
}
if(argc>=2){ // dua File name vao tu dong lenh
sprintf(fname,"%s",argv[1]);
}
else{// neu chua co File name thi bat dau nhap file name vao
printf("Bitte Filename eingeben\n");
fflush(stdin);
gets(fname);
}
iov[0].iov_base = fname;
iov[0].iov_len = strlen(fname)+1;
rc = sendmsg(sockd, &mh, 0); // guoi filename sang server
if(rc<0){
perror("sendmsg");
exit(3);
}
iov[0].iov_base = eab;
iov[0].iov_len = sizeof(eab);
rc = recvmsg(sockd, &mh, 0); // nhan thong bao va File descriptor tu server
cmp = CMSG_FIRSTHDR(&mh);
p = (int *)CMSG_DATA(cmp);
if(rc<0){
perror("recvmsg");
exit(4);
}
switch(eab[0]){// kiem tra thong bao
case 1:// file khong ton tai
printf("File ist nicht existiert!\n");
break;
case 2:// file ton tai
printf("File ist existiert. Filedeskriptor ist bereits zu verwandel!\n");
FAULT ================> fd = *p; //fault here with GDB debug
printf("fd=%d\n",fd);
fp = fdopen(fd,"r");
if(fp=NULL)
printf("fehler fd\n");
printf("Fileinhalt ausgeben\n");
printf("=============================================\n");
while(fread(eab,100,1,fp)>0)
printf("%s", eab);
printf("=============================================\n");
fclose(fp);
break;
}
close(sockd);
}
Вы можете проверить перед строкой 'fd = * p', если' p == 0'. Похоже на разуплотнение нулевого указателя – maverik
Первое, что вам нужно сделать, когда вы получаете аварийный сигнал или какой-либо другой, - запустить программу в отладчике. Это не только поможет вам определить местоположение аварии, но также позволит вам просмотреть переменные, чтобы помочь вам разобраться в причинах сбоя. –
@maverik думаю. если проблема остается в p == 0. Это означает, что клиент не может получить файловый дескриптор от Sever. ты знаешь почему? –