簡體   English   中英

MASM中的Winsock-bind函數錯誤(32位asm)

[英]Winsock-bind function error In MASM(32 BIT asm)

首先,對不起我的英語不好,英語不是我的母語。 因此,我正在嘗試在Assembly 32 BIT MASM中編寫聊天程序。

現在,我正在編寫服務器端代碼,到目前為止,我使用了WSAStartUp和Socket-Windows API函數,現在我正在嘗試使用Bind函數。

綁定功能的鏈接: https : //msdn.microsoft.com/zh-cn/library/windows/desktop/ms737550(v=vs.85).aspx

這是我到目前為止編寫的代碼(我的問題寫在代碼之后):

.386 
.MODEL Flat, STDCALL 
option casemap:none 

include \masm32\include\windows.inc 
include \masm32\include\Ws2_32.inc
includelib \masm32\lib\Ws2_32.lib
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib

.DATA 

Success db 'WSAStartUp Succseed!',0
NO_Success db 'WSAStartUp NOT Succseed....',0
Socketsu db 'Socket :(:(:(:(',0
SocketSuccess db 'Socket Success!! :)',0
Bindno db 'Bind Error',0
Bindyes db 'Bind Success! :)',0
LocalIP db "127.0.0.1",0
port dd 8020

.DATA? 

wsadata db 400 dup (?)      ;WSADATA struct that hold the information about the Windows Sockets implementation.(info ret from WSATSTARTUP)
flag dw ?
ListenSocket dd ?
SockAddrStruct db 30 dup (?)
;so sockaddr_in <?> 
sockaddrs db 16 dup (?)

.CONST 
    wVersionRequested equ 0101h
.CODE 
   main:
;-------------------WSAStartUp-----------------------;
        ;Initialize the work with winsock (WS StartUp = WINSOCK START UP)

             invoke WSAStartup,wVersionRequested, offset wsadata        
            .if eax!=0
                invoke MessageBoxA,NULL,offset NO_Success,offset NO_Success,MB_OK 
                jmp End_Program
            .else
                invoke MessageBoxA,NULL,offset Success,offset Success,MB_OK 
            .endif

;-------------------Socket-----------------------;

    ;AF_INET - address family(in format: host,port) to likboa the type of addresses that the socket can communicate with

    invoke socket,AF_INET,SOCK_STREAM,IPPROTO_TCP
    .IF eax==INVALID_SOCKET
        invoke MessageBoxA,NULL,offset Socketsu,offset Socketsu,MB_OK 
        jmp End_Program
     .else
       invoke MessageBoxA,NULL,offset SocketSuccess,offset SocketSuccess,MB_OK
       mov [ListenSocket],eax
    .ENDIF
;-------------------Bind-------------------------;
;SockAddr Struct:

mov eax,AF_INET
mov [dword ptr sockaddrs],eax
invoke htons,[port]
mov [dword ptr sockaddrs+2],eax
invoke inet_addr,[dword ptr LocalIP]   
mov [dword ptr sockaddrs+4],eax
invoke bind,SIZEOF sockaddrs,offset sockaddrs,ListenSocket

.if eax==0
    invoke MessageBoxA,NULL,offset Bindyes,offset Bindyes,MB_OK
.else
    invoke MessageBoxA,NULL,offset Bindno,offset Bindno,MB_OK
.endif


End_Program:
        invoke ExitProcess,0 
end main

我不知道是什么問題。 但是當我運行代碼時,我得到的消息框是:Bind Error。

我猜想這是sockaddrs結構中的一個問題(我在其中添加值的方式)。 但是我不知道我需要更改什么以及如何解決它。

我以為可能使用WSAGetLastError函數查看錯誤是什么,但我不知道如何打印該函數返回的值並查看錯誤是什么(我不能將其放在調用MessageBox中,而參數為EAX(保留返回值的寄存器))。

那么有人可以幫我解決“綁定”部分中的問題嗎?

WSAGetLastError

你有幾個問題。 首先,我將為您提供一種檢索代表最后WSAGetLastError的消息的方法(它也可以與GetLastError )。 Win32 API的方法是使用FormatMessage轉換WSAGetLastError返回的錯誤消息代碼。 您可以在此處找到MSDN上有關FormatMessage的信息,以及與我們將使用的代碼類似的示例 它定義為:

DWORD WINAPI FormatMessage(

在DWORD dwFlags中,
In_opt LPCVOID lpSource,
在DWORD dwMessageId中,
在DWORD dwLanguageId中,
輸出LPTSTR lpBuffer,
在DWORD nSize中,
In_opt va_list *參數
);

在您的.DATA? 區域中,添加一個變量來存儲我們將從FormatMessage返回的緩沖區指針:

lpErrorMsg  dd  ? 

若要檢索並顯示上一個WSA錯誤,可以在與套接字相關的調用(例如bind )之后使用類似以下的內容:

.if eax==SOCKET_ERROR
    invoke WSAGetLastError
    invoke FormatMessageA, FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, eax, LANG_NEUTRAL, offset lpErrorMsg, 0, NULL
    invoke MessageBoxA,NULL,lpErrorMsg,offset Bindno,MB_OK
.endif

錯誤修復

您的代碼中存在許多問題。 我觀察到的第一個port是32位整數,因此應將其定義為:

port dd 8020

如果不進行此更改,則htons將無法正常運行,因為它期望使用32位Integer。

下一個錯誤是在這里:

invoke MessageBoxA,NULL,offset SocketSuccess,offset SocketSuccess,MB_OK
mov [ListenSocket],eax

您正在通過首先調用MessageBoxA來破壞eax 您可能打算先保存它:

mov [ListenSocket],eax
invoke MessageBoxA,NULL,offset SocketSuccess,offset SocketSuccess,MB_OK

此代碼中似乎存在許多問題:

mov eax,AF_INET
mov [dword ptr sockaddrs],eax

這是不正確的,因為它適用於32位整數,並且我們需要一個WORD (16位)。 它應該是:

mov ax,AF_INET
mov [word ptr sockaddrs],ax

這也需要使用16位WORD存儲在sockaddrs+2

invoke htons,[port]
mov [dword ptr sockaddrs+2],eax

因此應該是:

invoke htons,[port]
mov [word ptr sockaddrs+2],ax

這是不正確的,因為我們不想取消引用LocalIP的地址,而只想要LocalIP的地址:

invoke inet_addr,[dword ptr LocalIP]   
mov [dword ptr sockaddrs+4],eax

因此,這似乎更正確:

invoke inet_addr, offset LocalIP   
mov [dword ptr sockaddrs+4],eax

然后,您將參數混合在一起進行bind 你有過:

invoke bind,SIZEOF sockaddrs,offset sockaddrs,ListenSocket

應該是:

invoke bind,ListenSocket,offset sockaddrs,SIZEOF sockaddrs

使用sockaddr_in的更簡單方法

MASM32定義了一個帶有所有已定義字段的sockaddr_in 為了使使用此結構更容易並使代碼更易讀,您可能需要考慮將SockAddrStruct定義為(並清零):

SockAddrStruct sockaddr_in <0>

使用這種方式定義了SockAddrStruct您現在可以更改套接字代碼以讀取如下內容:

;-------------------Bind-------------------------;
;SockAddr Struct:

mov SockAddrStruct.sin_family,AF_INET
invoke htons, [port]
mov SockAddrStruct.sin_port,ax
invoke inet_addr, offset LocalIP   
mov SockAddrStruct.sin_addr.S_un.S_addr, eax
invoke bind,ListenSocket,offset SockAddrStruct,SIZEOF SockAddrStruct

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM