通訊端(socket)當今已成為最流行的網路通訊應用程式介面。通訊端最初是由加利福尼亞大學Berkeley分校為Unix作業系統開發的網路通訊介面,後來它又被移植到DOS與Windows系統,特別是近幾年來互連網絡在全世界範圍內被廣泛普及並且增長迅猛,進一步奠定了它在網路通訊程式開發領域的主宰地位。跨系統網路互聯的呼聲在我國也越來越高。近來,在開發的銀行與證券連網系統中,我們嘗試做了由Unix Sockets到Windows Sockets通訊應用程式的移植,有所體會,望能將移植過程中應該注意的幾點問題與熱心於這方面工作的人們共同作以探討,以期能起到拋磚引玉的作用。
- 修改標頭檔的定義
在Unix Sockets應用程式中包含標頭檔的語句為#include<sys/socket.h>,而在Windows Sockets應用程式中相應語句應為 #include<winsock.h>。
Unix Sockets應用程式中包含標頭檔的語句為#include<sys/socket.h>,而在Windows Sockets應用程式中相應語句應為 #include<winsock.h>。
Windows Sockets的實現由兩部分組成,即開發組件與運行組件。開發組件是供程式員開發Windows Sockets 應用程式使用的,它包括Windows Sockets應用程式介面函數庫、標頭檔以及一些介紹Windows Sockets實現的文檔,其中標頭檔winsock.h中包含了Windows Sockets 實現所定義的宏、常數值、資料結構和函數調用介面原型。Winsock.h是編寫Windows Sockets應用程式必須包含的標頭檔。
的實現由兩部分組成,即開發組件與運行組件。開發組件是供程式員開發Windows Sockets 應用程式使用的,它包括Windows Sockets應用程式介面函數庫、標頭檔以及一些介紹Windows Sockets實現的文檔,其中標頭檔winsock.h中包含了Windows Sockets 實現所定義的宏、常數值、資料結構和函數調用介面原型。Winsock.h是編寫Windows Sockets應用程式必須包含的標頭檔。
- Windows Sockets DLL初始化與資源釋放
在Windows Sockets的介面函數中,提供了WSAStartup()與WSACleanup()兩個函數,用於在程式開始時初始化Windows Sockets DLL和程式結束時釋放Windows Sockets DLL資源,它們是編寫Windows Sockets應用程式時必須使用的兩個函數。
Windows Sockets的介面函數中,提供了WSAStartup()與WSACleanup()兩個函數,用於在程式開始時初始化Windows Sockets DLL和程式結束時釋放Windows Sockets DLL資源,它們是編寫Windows Sockets應用程式時必須使用的兩個函數。
- 將通訊端的類型由int改為SOCKET
在Unix系統中,通訊端類型定義為int型,而在Windows系統中,通訊端類型被定義為SOCKET型,即unsigned int型。
Unix系統中,通訊端類型定義為int型,而在Windows系統中,通訊端類型被定義為SOCKET型,即unsigned int型。
- 錯誤碼的擷取與設定
在Unix系統中,擷取、設定錯誤碼使用全域變數errno,而在Windows系統中則應將其改為用函數WSAGetLastError()和WSASetLastError()。Windows Sockets 為了與多線程環境相容,提供了兩個出錯處理函數WSAGetLastError()與WSASetLastError()來擷取與設定當前線程的最近錯誤號碼,而不再使用Unix系統中的全域變數errno和h_errno。
Unix系統中,擷取、設定錯誤碼使用全域變數errno,而在Windows系統中則應將其改為用函數WSAGetLastError()和WSASetLastError()。Windows Sockets 為了與多線程環境相容,提供了兩個出錯處理函數WSAGetLastError()與WSASetLastError()來擷取與設定當前線程的最近錯誤號碼,而不再使用Unix系統中的全域變數errno和h_errno。
- 關閉通訊端
在Unix系統中使用close()函數來關閉通訊端,而在Windows系統中則用closesocket()函數。
Unix系統中使用close()函數來關閉通訊端,而在Windows系統中則用closesocket()函數。
- 對通訊端的控制
在Unix系統中,使用ioctl()函數和fcntl()函數實現對通訊端的控制,而在Windows系統中則應使用ioctlsocket()函數。
Unix系統中,使用ioctl()函數和fcntl()函數實現對通訊端的控制,而在Windows系統中則應使用ioctlsocket()函數。
- getsockopt()和setsockopt()函數的處理
在Unix Sockets和Windows Sockets中對這兩個函數提供的支援不同。在Windows Sockets中getsockopt()與setsockopt()不支援的Berkeley Sockets選項有:
SO_RCVLOWAT 接受低潮標誌
SO_RCVTIMEO 接受逾時
SO_SNDLOWAT 發送低潮標誌
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
Unix Sockets和Windows Sockets中對這兩個函數提供的支援不同。在Windows Sockets中getsockopt()與setsockopt()不支援的Berkeley Sockets選項有:
SO_RCVLOWAT 接受低潮標誌
SO_RCVTIMEO 接受逾時
SO_SNDLOWAT 發送低潮標誌
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_RCVLOWAT 接受低潮標誌
SO_RCVTIMEO 接受逾時
SO_SNDLOWAT 發送低潮標誌
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_RCVTIMEO 接受逾時
SO_SNDLOWAT 發送低潮標誌
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_SNDLOWAT 發送低潮標誌
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
- 使用宏FD_XXX來控制fd_set結構
由於Windows Sockets 某些函數在介面上雖然與Unix Sockets一致,但是它們的內部實現卻不一樣,例如,在函數select()的參數中,Unix Sockets實現通訊端集合使用的是位元遮罩,但在Windows Sockets中卻是使用一個SOCKET的數組。雖然通訊端的集合仍由fd_set類型表示,但在Unix Sockets 源檔案中直接修改fd_set結構的代碼在Windows Sockets環境下將不能正常工作。因此,在進行移植時應將來源程式中對結構fd_set的直接修改改為通過使用FD_XXX宏來修改。
Windows Sockets 某些函數在介面上雖然與Unix Sockets一致,但是它們的內部實現卻不一樣,例如,在函數select()的參數中,Unix Sockets實現通訊端集合使用的是位元遮罩,但在Windows Sockets中卻是使用一個SOCKET的數組。雖然通訊端的集合仍由fd_set類型表示,但在Unix Sockets 源檔案中直接修改fd_set結構的代碼在Windows Sockets環境下將不能正常工作。因此,在進行移植時應將來源程式中對結構fd_set的直接修改改為通過使用FD_XXX宏來修改。
- 應在Windows Sockets程式中盡量使用WSA宏
在Windows Sockets的標頭檔中定義了許多以WSA開頭的宏,在程式中使用這些宏,可以大大地增加程式的可讀性。例如:
Windows Sockets的標頭檔中定義了許多以WSA開頭的宏,在程式中使用這些宏,可以大大地增加程式的可讀性。例如:
errno = WSAGetLastError();
;
if (errno = WSAEWOULDBLOCK) {
……
) {
……
……
}
這些宏是Windows Sockets就應用程式實現過程中可能會出現的錯誤,為便於程式的讀寫而專門做出的擴充,它是Windows Sockets應用程式編寫人員開發程式時共同遵循的規範,因此應盡量使用這些宏,以增加程式的可讀性。
Windows Sockets就應用程式實現過程中可能會出現的錯誤,為便於程式的讀寫而專門做出的擴充,它是Windows Sockets應用程式編寫人員開發程式時共同遵循的規範,因此應盡量使用這些宏,以增加程式的可讀性。
- 阻塞調用的處理
Windows是非搶先多任務環境,各任務之間的切換是通過訊息驅動的,如果一個應用程式不能主動放棄其控制權,別的應用程式就不能夠執行,這一點與Unix作業系統有著本質的區別。對於從Unix Sockets環境中移植來的應用程式來說,阻塞問題必須考慮。
為解決阻塞問題,Windows Sockets特增設了如下幾個阻塞處理函數:
是非搶先多任務環境,各任務之間的切換是通過訊息驅動的,如果一個應用程式不能主動放棄其控制權,別的應用程式就不能夠執行,這一點與Unix作業系統有著本質的區別。對於從Unix Sockets環境中移植來的應用程式來說,阻塞問題必須考慮。
為解決阻塞問題,Windows Sockets特增設了如下幾個阻塞處理函數:
Windows Sockets特增設了如下幾個阻塞處理函數:
WSAIsBlocking() 檢測阻塞調用是否進行中
WSACancelBlockingCall() 取消一個進行中的阻塞調用
WSASetBlocking() 設定自己的阻塞處理常式
WSAUnhookBlockingHook() 恢複預設的阻塞處理常式
為不影響原來環境中的阻塞處理常式,在安裝自己的阻塞處理常式時,應注意儲存返回的先前安裝的阻塞處理常式的程式執行個體指標,並在處理結束後恢複。
檢測阻塞調用是否進行中
WSACancelBlockingCall() 取消一個進行中的阻塞調用
WSASetBlocking() 設定自己的阻塞處理常式
WSAUnhookBlockingHook() 恢複預設的阻塞處理常式
為不影響原來環境中的阻塞處理常式,在安裝自己的阻塞處理常式時,應注意儲存返回的先前安裝的阻塞處理常式的程式執行個體指標,並在處理結束後恢複。
WSACancelBlockingCall() 取消一個進行中的阻塞調用
WSASetBlocking() 設定自己的阻塞處理常式
WSAUnhookBlockingHook() 恢複預設的阻塞處理常式
為不影響原來環境中的阻塞處理常式,在安裝自己的阻塞處理常式時,應注意儲存返回的先前安裝的阻塞處理常式的程式執行個體指標,並在處理結束後恢複。
WSASetBlocking() 設定自己的阻塞處理常式
WSAUnhookBlockingHook() 恢複預設的阻塞處理常式
為不影響原來環境中的阻塞處理常式,在安裝自己的阻塞處理常式時,應注意儲存返回的先前安裝的阻塞處理常式的程式執行個體指標,並在處理結束後恢複。
WSAUnhookBlockingHook() 恢複預設的阻塞處理常式
為不影響原來環境中的阻塞處理常式,在安裝自己的阻塞處理常式時,應注意儲存返回的先前安裝的阻塞處理常式的程式執行個體指標,並在處理結束後恢複。
- 盡量將阻塞調用改為基於訊息的非同步作業
Windows Sockets程式中盡量使用WSA宏
FD_XXX來控制fd_set結構
和setsockopt()函數的處理
int改為SOCKET
初始化與資源釋放
在Unix Sockets應用程式中包含標頭檔的語句為#include<sys/socket.h>,而在Windows Sockets應用程式中相應語句應為 #include<winsock.h>。
Unix Sockets應用程式中包含標頭檔的語句為#include<sys/socket.h>,而在Windows Sockets應用程式中相應語句應為 #include<winsock.h>。
Windows Sockets的實現由兩部分組成,即開發組件與運行組件。開發組件是供程式員開發Windows Sockets 應用程式使用的,它包括Windows Sockets應用程式介面函數庫、標頭檔以及一些介紹Windows Sockets實現的文檔,其中標頭檔winsock.h中包含了Windows Sockets 實現所定義的宏、常數值、資料結構和函數調用介面原型。Winsock.h是編寫Windows Sockets應用程式必須包含的標頭檔。
的實現由兩部分組成,即開發組件與運行組件。開發組件是供程式員開發Windows Sockets 應用程式使用的,它包括Windows Sockets應用程式介面函數庫、標頭檔以及一些介紹Windows Sockets實現的文檔,其中標頭檔winsock.h中包含了Windows Sockets 實現所定義的宏、常數值、資料結構和函數調用介面原型。Winsock.h是編寫Windows Sockets應用程式必須包含的標頭檔。
- Windows Sockets DLL初始化與資源釋放
在Windows Sockets的介面函數中,提供了WSAStartup()與WSACleanup()兩個函數,用於在程式開始時初始化Windows Sockets DLL和程式結束時釋放Windows Sockets DLL資源,它們是編寫Windows Sockets應用程式時必須使用的兩個函數。
Windows Sockets的介面函數中,提供了WSAStartup()與WSACleanup()兩個函數,用於在程式開始時初始化Windows Sockets DLL和程式結束時釋放Windows Sockets DLL資源,它們是編寫Windows Sockets應用程式時必須使用的兩個函數。
- 將通訊端的類型由int改為SOCKET
在Unix系統中,通訊端類型定義為int型,而在Windows系統中,通訊端類型被定義為SOCKET型,即unsigned int型。
Unix系統中,通訊端類型定義為int型,而在Windows系統中,通訊端類型被定義為SOCKET型,即unsigned int型。
- 錯誤碼的擷取與設定
在Unix系統中,擷取、設定錯誤碼使用全域變數errno,而在Windows系統中則應將其改為用函數WSAGetLastError()和WSASetLastError()。Windows Sockets 為了與多線程環境相容,提供了兩個出錯處理函數WSAGetLastError()與WSASetLastError()來擷取與設定當前線程的最近錯誤號碼,而不再使用Unix系統中的全域變數errno和h_errno。
Unix系統中,擷取、設定錯誤碼使用全域變數errno,而在Windows系統中則應將其改為用函數WSAGetLastError()和WSASetLastError()。Windows Sockets 為了與多線程環境相容,提供了兩個出錯處理函數WSAGetLastError()與WSASetLastError()來擷取與設定當前線程的最近錯誤號碼,而不再使用Unix系統中的全域變數errno和h_errno。
- 關閉通訊端
在Unix系統中使用close()函數來關閉通訊端,而在Windows系統中則用closesocket()函數。
Unix系統中使用close()函數來關閉通訊端,而在Windows系統中則用closesocket()函數。
- 對通訊端的控制
在Unix系統中,使用ioctl()函數和fcntl()函數實現對通訊端的控制,而在Windows系統中則應使用ioctlsocket()函數。
Unix系統中,使用ioctl()函數和fcntl()函數實現對通訊端的控制,而在Windows系統中則應使用ioctlsocket()函數。
- getsockopt()和setsockopt()函數的處理
在Unix Sockets和Windows Sockets中對這兩個函數提供的支援不同。在Windows Sockets中getsockopt()與setsockopt()不支援的Berkeley Sockets選項有:
SO_RCVLOWAT 接受低潮標誌
SO_RCVTIMEO 接受逾時
SO_SNDLOWAT 發送低潮標誌
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
Unix Sockets和Windows Sockets中對這兩個函數提供的支援不同。在Windows Sockets中getsockopt()與setsockopt()不支援的Berkeley Sockets選項有:
SO_RCVLOWAT 接受低潮標誌
SO_RCVTIMEO 接受逾時
SO_SNDLOWAT 發送低潮標誌
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_RCVLOWAT 接受低潮標誌
SO_RCVTIMEO 接受逾時
SO_SNDLOWAT 發送低潮標誌
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_RCVTIMEO 接受逾時
SO_SNDLOWAT 發送低潮標誌
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_SNDLOWAT 發送低潮標誌
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_SNDTIMEO 發送逾時
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
IP_OPTIONS 取得IP頭中的選項
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
TCP_MAXSEG 取得TCP最大尺寸
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_ACCEPTCONN 通訊端正在監聽
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由WSAGetLastError()函數返回。
由於提供的支援不同,進行移植時若有必要應修改相應的來源程式。
SO_ERROR 取錯誤狀態並清除
SO_TYPE 通訊端類型
使用不支援的選項將返回錯誤碼WSAENOPROTOOPT,它由W