我正在尝试编写一个客户端程序和一个服务器程序,当客户端连接到服务器时,服务器会将文件中的随机字符串发送回它。这是我到目前为止(从文件中省略):
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
int listfd;
int connfd;
int main(int argc, char *argv[]){
/*
* Create Sockets
*/
listfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(listfd == -1)
exit(-1);
struct sockaddr saddr = {AF_UNIX, "server"};
socklen_t saddrlen = sizeof(struct sockaddr) + 6;
bind(listfd, &saddr, saddrlen);
listen(listfd, 10);
fflush(stdout);
printf("Running...\n");
/*
* Listen for connections
* and send random phrase on accept
*/
while(1){
connfd = accept(listfd, NULL, NULL);
int r = rand() % num_of_lines; //Pick random phrase/hint pair
write(connfd, phrases[r], strlen(phrases[r]));
close(connfd);
sleep(1);
}
exit(0);
}
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ioctl.h>
int main(int argc, char *argv[])
{
int sock;
int conn;
struct sockaddr saddr = {AF_UNIX, "server"};
socklen_t saddrlen = sizeof(struct sockaddr) + 6;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
conn = connect(sock, &saddr, saddrlen);
char BUFF[1024];
read(sock, BUFF, 1024);
printf("%s", BUFF);
return 0;
}
当我尝试在客户端打印时出现问题。我运行服务器,但是当我运行客户端时,它只打印垃圾字符,我不完全确定是什么导致了这一点。
非常感谢任何帮助,谢谢!
我发现了我的问题。因为服务器套接字绑定到“服务器”,这也是可执行文件的名称,这导致了很多问题。
重命名sockaddr.sa_data字段修复了我的问题。
答案 0 :(得分:6)
你有很多问题。这是错的:
struct sockaddr saddr = {AF_UNIX, "server"};
socklen_t saddrlen = sizeof(struct sockaddr) + 6;
你告诉内核“这是一个代表套接字地址的字节包。它是sizeof(struct sockaddr) + 6
字节长”,但你只传递sizeof(struct sockaddr)
个字节。结果:内核读取您的地址超出范围,最多导致系统调用失败并导致EFAULT
,最坏情况导致内核读入垃圾数据。
设置AF_UNIX
套接字地址的正确方法是使用用于AF_UNIX
套接字的套接字地址类型,即struct sockaddr_un
(参见unix(7)
):
struct sockaddr_un saddr = {AF_UNIX, "/socket/path"};
bind(listfd, (struct sockaddr *)&saddr, sizeof(saddr));
同样,调用connect(2)
的客户端代码也应该以相同的方式设置地址。
接下来,您需要检查错误。几乎所有系统调用都可能失败,因此您需要在每次调用后检查失败并正确处理它(通常关闭套接字和/或使用适当的错误消息终止进程)。
正如您所提到的,您还需要为套接字选择合适的路径名。名为AF_UNIX
的套接字存在于文件系统中,因此不能与任何其他文件共享相同的名称,包括服务器和客户端程序。
您对read(2)
的调用需要使用返回值来确定读取的字节数。它不会终止其输出 - 如果它读取4个字节,那么这4个字节将在您的缓冲区中,之后的所有其他内容将是不确定的。由于printf
期望其输入为空终止,因此您需要自己显式地将其终止,或者传递长度,例如:
int n = read(sock, BUFF, sizeof(BUFF));
if (n < 0) { /* Handle error */ }
printf("%.*s", n, BUFF);
答案 1 :(得分:1)
read(sock, BUFF, 1024);
没有NULL终止缓冲区。你需要明确地做。它返回读取的字节数,并将许多字节复制到缓冲区。
readlen = read(sock, BUFF, 1024);
BUFF[readlen] = '\0';
检查connect
和read
的返回值是否有任何错误。检查服务器发送的内容。