简体   繁体   中英

Segmentation fault on Socket programming

I have a homework problem. Socket-Programming with Unix domain
1. Client send file name to server
2. Server checks the File exists, opens, and sends file descriptor to client
3. Client opens a file descriptor and outputs to screen. platform = ubuntu 12.04. I have problem with the client. Error Segmentation fault (core dumped) on line fd = *p (i have marked on client code)
this is my code

Server

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

In theory, you can't share file descriptors between processes over TCP sockets with processes with different address spaces. In order to do that, you could use UNIX sockets.

If you want to share info between processes (not file descriptors), you can use other techniques, like mmap , pipes , message passing, and so on.

You need to check the error code returned by recvmesg before you do anything with the data it may or may not have returned.

There is no guarantee that when recvmesg returns an error that mh will be in a useable state.

A segmentation fault on *p means that p is either zero or pointing to memory that is not allocated.

It looks like p is supposed to be pointing inside mh somewhere. First check that the value of p just before the crash is between &mh and (char*)&mh + sizeof(mh) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM