x86_64汇编实现Web服务器:socket/bind/listen调用异常排查
x86_64汇编Web服务器bind操作失败排查
我尝试用x86_64汇编编写Web服务器,尽管传入了正确参数,服务器始终无法完成bind操作。将参数传入自定义函数测试时,所有函数均未返回-1,但尝试连接localhost端口6000时,收到如下错误:
Failed to connect to localhost port 6000 after 0 ms: Couldn't connect to server
相关汇编代码如下:
section .text extern socket, bind, listen, accept, perror global main main: ; allocating sockaddr_in sub rsp, SIZE_OF_SERVER_ADDR ; ; sin_family mov word [rsp], AF_INET ; ; sin_port mov word [rsp + 2], PORT ; ; s_addr mov dword [rsp + 4], INADDR_ANY ; ; unsigned char data[8] mov qword [rsp + 8], 0x0 mov rdi, AF_INET mov rsi, SOCK_STREAM mov rdx, 0 call socket cmp rax, 0 jl exit_socket_error ; holding the socket_fd mov r12, rax mov rdi, r12 mov rsi, rsp mov rdx, SIZE_OF_SERVER_ADDR call bind cmp rax, 0 jl exit_bind_error mov rdi, r12 mov rsi, 10 call listen cmp rax, 0 jl exit_error call listening_msg while: mov rdi, r12 mov rsi, rsp mov rdx, 4 call accept cmp rax, 0 jl exit_error call client_connect jmp while
问题排查与修复方案
1. 端口号未转换为网络字节序
TCP/IP协议要求端口号必须使用网络字节序(大端序),但x86_64架构是小端序,直接将PORT赋值给sin_port会导致端口解析错误。需要用htons()函数转换端口号:
section .text extern socket, bind, listen, accept, perror, htons ; 添加htons声明 global main ; ... 其他代码 ... ; ; sin_port mov rdi, PORT call htons mov word [rsp + 2], ax ; 写入转换后的大端序端口
2. 检查SIZE_OF_SERVER_ADDR的定义
struct sockaddr_in在x86_64系统中的标准大小是16字节,确保SIZE_OF_SERVER_ADDR宏被定义为16,否则bind会因地址长度不匹配失败。
3. accept调用参数错误
当前accept的第三个参数传的是4,不符合系统调用要求。需要传入指向struct socklen_t变量的指针,且该变量初始化为地址结构的大小:
while: ; 在栈上准备socklen_t变量 mov dword [rsp - 4], SIZE_OF_SERVER_ADDR mov rdi, r12 mov rsi, rsp ; 客户端地址缓冲区 mov rdx, rsp - 4 ; socklen_t变量指针 call accept
4. 完善错误处理
当前代码在错误分支未打印具体错误信息,建议在exit_bind_error等分支中调用perror输出系统错误:
exit_bind_error: mov rdi, "bind failed" call perror ; 退出程序 mov rax, 60 ; exit系统调用号 mov rdi, 1 syscall
内容的提问来源于stack exchange,提问作者WasixXD
相关产品推荐
相关产品推荐

