在 C 中使用 bind() 的无效参数
Invalid argument using bind() in C
这是应该创建套接字并进行绑定的代码
#include<stdio.h>
#include<stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <sys/un.h>
#include <unistd.h>
#define SOCKNAME "./serverSC"
#define RETURNSYSCALL(r, c, e) if((r=c) == -1) {perror(e); exit(errno);}
#define SYSCALL(c, e) if(c == -1) {perror(e); exit(errno);}
void cleanup();
int main()
{
cleanup();
atexit(cleanup);
int socketFd, socketComFd;
struct sockaddr_un socketName;
memset(&socketName, '0', sizeof(socketName));
socketName.sun_family = AF_UNIX;
strncpy(socketName.sun_path, SOCKNAME, strlen(SOCKNAME)+1);
RETURNSYSCALL(socketFd, socket(AF_UNIX, SOCK_STREAM, 0), "Impossibile creare una socket");
SYSCALL(bind(socketFd, (struct sockaddr *) &socketName, sizeof(socketFd)), "Impossibile fare la bind");
SYSCALL(listen(socketFd, 10), "Impossibile fare la listen");
RETURNSYSCALL(socketComFd, accept(socketFd, NULL, 0), "impossibile fare la accept");
return 0;
}
void cleanup() {
unlink(SOCKNAME);
}
但是它打印的输出是:
Impossibile fare la bind: Invalid argument
有些人建议使用“AF_INET”而不是“AF_UNIX”,但这也不起作用。
bind()
的第三个参数是地址的大小,所以在本例中应该是sizeof(socketName)
,而不是sizeof(socketFd)
.
memset(&socketName, '0', sizeof(socketName));
'0'
毫无意义。使用 0
(无引号)。
strncpy(socketName.sun_path, SOCKNAME, strlen(SOCKNAME)+1);
strncpy
的大小参数意味着 目标缓冲区 的大小,而不是源字符串。后者是完全无用的。如果你想复制整个源字符串,只需使用 strcpy
,它就是这样做的。此外,strncpy
是一个危险的函数,应谨慎使用。它不一定以 null 终止目标缓冲区,人们往往会忘记这一点。如果你坚持,就这样做:
strncpy (socketName.sun_path, SOCKNAME, sizeof(socketName.sun_path));
socketName.sun_path[sizeof(socketName.sun_path) - 1] = 0;
最后,sizeof(socketFd)
应该是 sizeof(socketName)
。
这是应该创建套接字并进行绑定的代码
#include<stdio.h>
#include<stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <sys/un.h>
#include <unistd.h>
#define SOCKNAME "./serverSC"
#define RETURNSYSCALL(r, c, e) if((r=c) == -1) {perror(e); exit(errno);}
#define SYSCALL(c, e) if(c == -1) {perror(e); exit(errno);}
void cleanup();
int main()
{
cleanup();
atexit(cleanup);
int socketFd, socketComFd;
struct sockaddr_un socketName;
memset(&socketName, '0', sizeof(socketName));
socketName.sun_family = AF_UNIX;
strncpy(socketName.sun_path, SOCKNAME, strlen(SOCKNAME)+1);
RETURNSYSCALL(socketFd, socket(AF_UNIX, SOCK_STREAM, 0), "Impossibile creare una socket");
SYSCALL(bind(socketFd, (struct sockaddr *) &socketName, sizeof(socketFd)), "Impossibile fare la bind");
SYSCALL(listen(socketFd, 10), "Impossibile fare la listen");
RETURNSYSCALL(socketComFd, accept(socketFd, NULL, 0), "impossibile fare la accept");
return 0;
}
void cleanup() {
unlink(SOCKNAME);
}
但是它打印的输出是:
Impossibile fare la bind: Invalid argument
有些人建议使用“AF_INET”而不是“AF_UNIX”,但这也不起作用。
bind()
的第三个参数是地址的大小,所以在本例中应该是sizeof(socketName)
,而不是sizeof(socketFd)
.
memset(&socketName, '0', sizeof(socketName));
'0'
毫无意义。使用 0
(无引号)。
strncpy(socketName.sun_path, SOCKNAME, strlen(SOCKNAME)+1);
strncpy
的大小参数意味着 目标缓冲区 的大小,而不是源字符串。后者是完全无用的。如果你想复制整个源字符串,只需使用 strcpy
,它就是这样做的。此外,strncpy
是一个危险的函数,应谨慎使用。它不一定以 null 终止目标缓冲区,人们往往会忘记这一点。如果你坚持,就这样做:
strncpy (socketName.sun_path, SOCKNAME, sizeof(socketName.sun_path));
socketName.sun_path[sizeof(socketName.sun_path) - 1] = 0;
最后,sizeof(socketFd)
应该是 sizeof(socketName)
。