Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 如何在nasm中使用recvfrom获取UDP数据包的源IP地址?_Sockets_Udp_Ip_Nasm_Recvfrom - Fatal编程技术网

Sockets 如何在nasm中使用recvfrom获取UDP数据包的源IP地址?

Sockets 如何在nasm中使用recvfrom获取UDP数据包的源IP地址?,sockets,udp,ip,nasm,recvfrom,Sockets,Udp,Ip,Nasm,Recvfrom,我正在nasm中编写UDP套接字,并使用recvfrom系统调用从客户端接收UDP数据包 我可以成功地发送消息,但我想向客户端发送回复。 问题是我无法提取数据包的源IP地址,因此无法使用sendto系统调用 这是UDP服务器的代码: %include "../StandardLibrary/standardlib.inc" %include "./network.inc" PORT_NUMBER equ 4096 %macro printError 3 print %1 pr

我正在nasm中编写UDP套接字,并使用recvfrom系统调用从客户端接收UDP数据包

我可以成功地发送消息,但我想向客户端发送回复。 问题是我无法提取数据包的源IP地址,因此无法使用sendto系统调用

这是UDP服务器的代码:

%include "../StandardLibrary/standardlib.inc"
%include "./network.inc"

PORT_NUMBER equ 4096

%macro printError 3
    print %1
    printLineInt %2, %3
%endmacro

%macro clearBuffer 1
    getLength %1

    mov r12, 0
    %%loop:
        mov [%1 + r12], byte 0
        inc r12
        cmp r11, r12
        jne %%loop

%endmacro

section .data
    sock_addr:
    istruc sockaddr_in
        at sockaddr_in.sin_family, dw AF_INET
        at sockaddr_in.sin_port, dw htons(PORT_NUMBER)
        at sockaddr_in.in_addr, db 00h, 00h, 00h, 00h
        at sockaddr_in.sin_zero, db 0, 0, 0, 0, 0, 0, 0, 0
    iend

    client_sockaddr:
    istruc sockaddr
        at sockaddr.sa_family, dw AF_INET
        at sockaddr.sa_data, db 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0
    iend

    ;Messaggi di successo
    so_creation_success db "Socket creato con successo", 0
    so_binding_success db "Binding del socket eseguito con successo", 0
    so_started_capturing db "Socket in ascolto di messaggi...", 0

    ;Messaggi di errore
    so_creation_error db "Errore nella creazione del socket: ", 0
    so_binding_error db "Errore nel binding del socket: ", 0
    so_capture_error db "Errore nella ricezione del messaggio: ", 0
    so_sending_error db "Errore nell'invio del messaggio: ", 0

section .bss
    buffer resb 100
    socket_fd resw 1
    error_code resq 1
    tmp resb 10

section .text
    global _start

_start:
    ;1) Creazione del socket
    mov rax, SYS_SOCKET
    mov rdi, AF_INET
    mov rsi, SOCK_DGRAM
    mov rdx, 0
    syscall

    cmp rax, -1
    jle _socket_error

    ;Carica nello stack il file descriptor
    mov [socket_fd], rax
    printLine so_creation_success

    ;2) Binding del socket
    mov rax, SYS_BIND
    mov rdi, [socket_fd]
    mov rsi, sock_addr
    mov rdx, sockaddr_in_size
    syscall

    cmp rax, -1
    jle  _binding_error
    printLine so_binding_success

    ;3) Ricezione dei messaggi
    _listen:
        mov rax, SYS_RECVFROM
        mov rdi, [socket_fd]
        mov rsi, buffer
        mov rdx, 20
        mov r10, 0
        mov r8, client_sockaddr
        mov r9, 16
        syscall

        cmp rax, -1          ;Controlla che non ci siano stati errori
        jle _capture_error   
        cmp rax, 1          ;Controlla che non sia stato ricevuto un pcchetto vuoto
        jle _exit           ;è definito vuoto anche un pacchetto con un solo carattere

        ;Messaggio ricevuto con successo
        print buffer
        clearBuffer buffer  ;Svuota il buffer
        jmp _listen

    ;Il programma è terminato con successo
    _exit:
        exit

    ;Errore nella creazione del socket
    _socket_error:
        neg rax
        mov [error_code], rax
        printError so_creation_error, [error_code], tmp
        exit [error_code]

    ;Errore durante il binding del socket
    _binding_error:
        neg rax
        mov [error_code], rax
        printError so_binding_error, [error_code], tmp
        exit [error_code]

    ;Errore durante la ricezione del messaggio
    _capture_error:
        neg rax
        mov [error_code], rax
        printError so_capture_error, [error_code], tmp
        exit [error_code]
在network.inc.上,我有:

SYS_SOCKET          equ 41  ;Id system call per la creazione del socket
SYS_SENDTO          equ 44  ;Id system call per l'invio di datagram UDP
SYS_RECVFROM        equ 45  ;Id system call per la ricezione di datagram UDP
SYS_BIND            equ 49  ;Id system call per legare un socket ad un indirizzo IP (o ad una famiglia)

AF_INET             equ 2   ;Rete IPv4
SOCK_DGRAM          equ 2   ;Id del protocollo UDP
INADDR_ANY          equ 0   ;Indica che il socket accetta comunicazioni da qualsiasi indirizzo IP

;Traduce x in un valore di tipo network byte order
%define htons(x) ((x >> 8) & 0xFF) | ((x & 0xFF) << 8)

;Rappresenta un indirizzo IPv4
struc in_addr
    .s_addr:        resb 4  ;Valore dei 4 ottetti
endstruc

;Rappresenta la struttura di un socket
struc sockaddr_in
    .sin_family:    resw 1  ;Id del tipo di indirizzo
    .sin_port:      resw 1  ;Numero di porta
    .in_addr:       resb 4  ;Indirizzo IP
    .sin_zero:      resb 8  ;Byte di rimepimento
endstruc

struc sockaddr
    .sa_family      resw 1
    .sa_data        resb 14
endstruc

作为UDP客户端,我正在使用netcat命令:netcat-u 127.0.0.1 4096

然后将填充结构与sendto syscall一起使用

UPD

sockaddr在C中具有以下形状:

我认为,在NASM中它看起来像这样:

struc sockaddr
    .sa_family resw 1
    .sa_data db 14
endstruc


client_sock_addr:
istruc sockaddr
    at sockaddr.sa_family, dw AF_INET
    at sockaddr.sa_data, db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
iend
UPD 2

我注意到您正在为套接字分配2个字节。实际上,套接字必须是int:

下一件事:您必须传递到r9引用,而不是值

section .data
    ; ...
    client_sockaddr_len dd 16
    ; ...

; ...
mov rax, SYS_RECVFROM
mov rdi, [socket_fd]
mov rsi, buffer
mov rdx, 20
mov r10, 0
mov r8, client_sockaddr
mov r9, client_sockaddr_len
syscall
最后你可以发送到


好的,但是我如何定义一个空的sockaddr结构呢?因为我以前已经尝试过这样做,但当我执行程序时,它会以-1默认错误地址退出。为了获得客户端地址,无论如何都应该使用sockaddr进行操作。请参阅更新的帖子。我已经尝试了您的解决方案,但仍然出现-1默认错误地址。我已经用我所做的更改更新了答案。注意到一些问题。检查应答只需将其直接发送到接收到的源地址,并将其直接用作sendto中的目标地址。根本不需要操纵它。
struc sockaddr
    .sa_family resw 1
    .sa_data db 14
endstruc


client_sock_addr:
istruc sockaddr
    at sockaddr.sa_family, dw AF_INET
    at sockaddr.sa_data, db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
iend
socket_fd resd 1
section .data
    ; ...
    client_sockaddr_len dd 16
    ; ...

; ...
mov rax, SYS_RECVFROM
mov rdi, [socket_fd]
mov rsi, buffer
mov rdx, 20
mov r10, 0
mov r8, client_sockaddr
mov r9, client_sockaddr_len
syscall
mov rax, SYS_SENDTO
mov rdi, [socket_fd]
mov rsi, buffer
mov rdx, 50
mov r10, 0
mov r8, client_sockaddr
mov r9, [client_sockaddr_len]
syscall