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.