我正在尝试编写一个客户端程序和一个服务器程序,当客户端连接到服务器时,服务器会将文件中的随机字符串发送回它.这是我到目前为止(从文件中省略):
#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);
}
Run Code Online (Sandbox Code Playgroud)
#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;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试在客户端打印时出现问题.我运行服务器,但是当我运行客户端时,它只打印垃圾字符,我不完全确定是什么导致了这一点.
非常感谢任何帮助,谢谢!
我想出了我的问题.因为服务器套接字绑定到"服务器",这也是可执行文件的名称,这导致了很多问题.
重命名sockaddr.sa_data字段修复了我的问题.
你有很多问题.这是错的:
struct sockaddr saddr = {AF_UNIX, "server"};
socklen_t saddrlen = sizeof(struct sockaddr) + 6;
Run Code Online (Sandbox Code Playgroud)
你告诉内核"这是一个代表套接字地址的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));
Run Code Online (Sandbox Code Playgroud)
同样,调用的客户端代码也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);
Run Code Online (Sandbox Code Playgroud)