[英]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
的消息的方法(它也可以與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
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.