Следующие C программы создают сокет-сервер и клиентский сервер, а также функции для отправки и извлечения из сокета дейтаграммы домена UNIX, чтобы отправлять сообщения из нескольких потоков на клиенте, отправлять в один поток-получатель на стороне сервера.
Конечные точки клиента и сервера создаются без ошибок, но когда я вызываю client_send, я получаю «неверный аргумент», и функция завершается ошибкой.
Я опубликовал более ранний вопрос по этой (UNIX дейтаграмме домена - «Неверный аргумент» в sendto ) и в одном полезном ответе сказал, что он подозревает, что const struct sockaddr * svaddr неверна. Однако подпись client_send происходит непосредственно из Linux справочных страниц (https://linux.die.net/man/2/sendto):
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
Соответственно, мой вызов отражает подпись со справочной страницы Linux :
ssize_t result = sendto(sfd, buf, msgLen, 0, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_un));
В качестве теста я попытался изменить указатель svaddr на вызов, чтобы исключить приведение:
ssize_t result = sendto(sfd, buf, msgLen, 0, svaddr, sizeof(struct sockaddr_un));
Но я получаю то же сообщение об ошибке "Недопустимый аргумент".
Вот код C:
#include <sys/un.h>
#include <sys/socket.h>
#include <ctype.h>
#include "tlpi_hdr_sockets.h"
#include "ud_ucase_sockets.h"
#include "error_functions_sockets.h"
#include "get_num_sockets.h"
#include "errno.h"
#define BUF_SIZE 750 /* Max size of messages between client to server */
#define SV_SOCK_PATH "/tmp/ud_ucase"
int64_t * create_socket_server(int64_t retvals[])
{
struct sockaddr_un svaddr, claddr;
int sfd, j;
ssize_t numBytes;
socklen_t len;
char buf[BUF_SIZE];
retvals[0] = 0;
retvals[1] = 0;
sfd = socket(AF_UNIX, SOCK_DGRAM, 0); /* Create server socket */
if (sfd == -1)
return retvals;
/* Construct well-known address and bind server socket to it */
if (remove(SV_SOCK_PATH) == -1 && errno != ENOENT)
return retvals;
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(svaddr.sun_path, SV_SOCK_PATH, sizeof(svaddr.sun_path) - 1);
if (bind(sfd, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_un)) == -1)
return retvals;
retvals[0] = sfd;
retvals[1] = (int64_t)&svaddr;
return retvals;
}
int64_t * create_socket_client(int64_t retvals[])
{
struct sockaddr_un claddr;
int sfd, j;
size_t msgLen;
ssize_t numBytes;
char resp[BUF_SIZE];
retvals[0] = 0;
retvals[1] = 0;
/* Create client socket; bind to unique pathname (based on PID) */
sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sfd == -1)
return retvals;
memset(&claddr, 0, sizeof(struct sockaddr_un));
claddr.sun_family = AF_UNIX;
snprintf(claddr.sun_path, sizeof(claddr.sun_path), "/tmp/ud_ucase_cl.%ld", (long) getpid());
retvals[0] = sfd;
retvals[1] = (int64_t)&claddr;
return retvals;
}
ssize_t client_send(int sfd, const void * buf, size_t msgLen, const struct sockaddr * svaddr)
{
ssize_t result = sendto(sfd, buf, msgLen, 0, svaddr, sizeof(struct sockaddr_un));
perror("socket");
if (result != msgLen)
return 0;
return result;
}
int64_t server_receive(int64_t sfd, void * buf, int64_t msgLen, const void * claddr)
{
socklen_t * len = (socklen_t * ) sizeof(struct sockaddr_un);
int numBytes = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *) claddr, len);
if (numBytes == -1)
return 0;
return numBytes;
}
int close_socket(socket_fd)
{
int closed = close(socket_fd);
return closed;
}
Программы C вызываются из NASM, где параметры в заголовке функции C передаются в rdi, rsi, rdx и rcx:
; Open the socket client
lea rdi,[retvals_cli] ; a 2-element int64 array
call create_socket_client wrt ..plt
mov rdi,rax
mov rax,[rdi]
mov [socket_client_fd],rax
mov rax,[rdi+8]
mov [socket_client_addr],rax
; Open the Socket Server
lea rdi,[retvals_svr] ; a 2-element int64 array
call create_socket_server wrt ..plt
mov rdi,rax
mov rax,[rdi]
mov [socket_server_fd],rax
mov rax,[rdi+8]
mov [socket_server_addr],rax
; Client_send
mov edi,[socket_client_fd]
mov rsi,[rbp-24]
mov rdx,720
lea rcx,[socket_server_addr]
mov r8,r15
call client_send wrt ..plt
Недопустимый параметр в этой строке client_send:
ssize_t result = sendto(sfd, buf, msgLen, 0, svaddr, sizeof(struct sockaddr_un));
Моя единственная проблема заключается в том, что после нескольких часов попыток разными способами передать параметры и вызвать его Я до сих пор не знаю, какой параметр неверен.
Спасибо за любую помощь.