1

我有一个家庭作业问题。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);
}

客户

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

3 回答 3

4

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

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

于 2012-12-12T12:59:46.433 回答
0

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

无法保证 whenrecvmesg返回的错误mh将处于可用状态。

于 2012-06-01T09:31:48.333 回答
0

分段错误*p表示 p 为零或指向未分配的内存。

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

于 2012-06-01T10:16:57.253 回答