Socket编程中的分段错误

Socket编程中的分段错误,c,linux,C,Linux,我有一个家庭作业问题。使用Unix域进行套接字编程 1.客户端向服务器发送文件名 2.服务器检查文件是否存在,打开并向客户端发送文件描述符 3.客户端打开一个文件描述符并输出到屏幕。 平台=ubuntu 12.04。 我和客户有问题。第fd=*p行错误分段错误(堆芯转储)(我已在客户端代码上标记) 这是我的密码 服务器 #include <stdlib.h> #include <stdio.h> #include <string.h> #include <

我有一个家庭作业问题。使用Unix域进行套接字编程
1.客户端向服务器发送文件名
2.服务器检查文件是否存在,打开并向客户端发送文件描述符
3.客户端打开一个文件描述符并输出到屏幕。 平台=ubuntu 12.04。 我和客户有问题。第
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);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义SOCKNAME“sockunix”
布尔恩德=假;
无效sigfkt(内部签名){
printf(“SIGINT empfangen…\n”);
ende=真;
}
int main(){
int fd、sockd、sockd2、rc、*p、sl;
文件*fp;
结构sockaddr_un uxadr;
结构msghdr mh;
结构cmsghdr*cmp;
char-ctrl[sizeof(struct-cmsghdr)+10];
结构iovec iov[1];
char-eab[100];
//巴特道开堡
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_标志=0;
cmp=CMSG_FIRSTHDR(&mh);
cmp->cmsg_len=cmsg_len(fd);
cmp->cmsg\U电平=SOL\U插座;
cmp->cmsg\U类型=SCM\U权限;
p=(int*)CMSG_数据(cmp);
//奎陶插座
uxadr.sun_family=AF_UNIX;
strcpy(uxadr.sun_路径,SOCKNAME);
sockd=socket(AF_UNIX,SOCK_STREAM,0);

如果(sockd您需要检查由
recvmesg
返回的错误代码,然后再对它可能返回或可能未返回的数据执行任何操作


无法保证当
recvmesg
返回错误时,
mh
将处于可用状态。

在对
recvmesg
返回的数据执行任何操作之前,您需要检查
recvmesg
返回的错误代码


无法保证当
recvmesg
返回错误时,
mh
将处于可用状态。

*p
上的分段故障表示p为零或指向未分配的内存


看起来p应该指向mh内部的某个地方。首先检查崩溃前p的值是否介于
&mh
(char*)&mh+sizeof(mh)
上的分段错误
*p
表示p为零或指向未分配的内存


看起来p应该指向mh内部的某个地方。首先检查碰撞前p的值是否介于
&mh
(char*)&mh+sizeof(mh)之间

理论上,您不能通过TCP套接字在具有不同地址空间的进程之间共享文件描述符。为此,您可以使用UNIX套接字


如果您想在进程(而不是文件描述符)之间共享信息,可以使用其他技术,如
mmap
、消息传递等。

理论上,您不能通过具有不同地址空间的进程的TCP套接字在进程之间共享文件描述符。为此,可以使用UNIX套接字


如果要在进程(而不是文件描述符)之间共享信息,您可以使用其他技术,如
mmap
、消息传递等。

如果
p==0
,是否可以在第行前检查
fd=*p
。看起来像空指针解引用当发生崩溃或任何类型的情况时,您应该做的第一件事是在调试器中运行程序。这不仅可以帮助您确定e崩溃,但也可以让您检查变量以帮助您找出崩溃的原因。@maverik我想是的。如果问题仍然存在于p==0。这意味着客户端无法从服务器接收文件描述符。您知道为什么吗?您能在第
fd=*p
行前检查
p==0
。看起来像是空指针解引用当y如果您遇到崩溃或任何类型的问题,就是在调试器中运行程序。这不仅可以帮助您确定崩溃的位置,还可以让您检查变量以帮助您找出崩溃的原因。@maverik我想是的。如果问题仍然存在于p==0。这意味着客户端无法从服务器接收文件描述符。您知道为什么吗?我已经检查了。这个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"

    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);
    }