"SOCKET"-PROGRAMMERING I WINDOWS-MILJÖ Winsock API består ungefär av samma funktioner som Socket Programming API i UNIX. Dessa funktioner deklareras i inkluderingsfilen <winsock.h> eller <winsock2.h> och de kompilerade funktionsdefinitionerna finns i filen winsock.dll. I BILAGA I beskrivs de nya funktionerna i Winsock 2.0. Detaljerad Winsock-dokumentation finns i Microsoft Developer Network (MSDN) Library, se http://msdn.microsoft.com/library och välj Windows Development -> Networking -> Windows Sockets 2 I stället för en "socket descriptor" har Winsock dock en egendefinierad datatyp med namnet "SOCKET". "Socket deskriptor" i UNIX motsvaras av en variabet med denna datatyp SOCKET s; Användning av "sockets" förutsätter att funktionen int WSAStartup(WORD wversionrequested, LPWSADATA lpwsadata); först anropas. WSAStartup returns zero if successful. Otherwise, it returns one of the error codes listed below. Note that the normal mechanism whereby the application calls WSAGetLastError to determine the error code cannot be used, since the Windows Sockets DLL may not have established the client data area where the "last error" information is stored. Efter användningen av "sockets" bör funktionen anropas. int WSACleanup (void); The return value of WSACleanup is zero if the operation was successful. Otherwise, the value SOCKET_ERROR is returned, and a specific error number may be retrieved by calling WSAGetLastError. An application or DLL is required to perform a successful WSAStartup call before it can use Windows Sockets services.
2 When it has completed the use of Windows Sockets, the application or DLL must call WSACleanup to deregister itself from a Windows. There must be a call to WSACleanup for every successful call to WSAStartup made by a task. Exempel: WORD wversionrequested; WSADATA wsadata; int err; wversionrequested = MAKEWORD( 2, 0 ); err = WSAStartup( wversionrequested, &wsadata ); if ( err!= 0 ) { } /* Tell the user that we couldn't find a usable */ /* WinSock DLL. */ return; /* Confirm that the WinSock DLL supports 2.0.*/ /* Note that if the DLL supports versions greater */ /* than 2.0 in addition to 2.0, it will still return */ /* 2.0 in wversion since that is the version we */ /* requested. */ if ( LOBYTE( wsadata.wversion )!= 2 HIBYTE( wsadata.wversion )!= 0 ) { /* Tell the user that we couldn't find a usable */ /* WinSock DLL. */ WSACleanup( ); return; }
3 FELHANTERING Felhanteringsfunktionen i Winsock är int WSAGetLastError (void); This function returns the last network error that occurred. When a particular Windows Sockets function indicates that an error has occurred, this function should be called to retrieve the appropriate error code. Felkoderna hittas under Winsock Reference i MSDN Library samt i Windows "help"-filen om Winsock med sökordet "Error Codes" Varje felkod har ett nummer och ett symboliskt namn. Nedan visas de två första felkoderna i förteckningen i Window "help"-filen om Winsock 2.0. The following is a list of possible error codes returned by the WSAGetLastError call, along with their extended explanations. Errors are listed in alphabetical order by error macro. Some error codes defined in WINSOCK2.H are not returned from any function - these have not been listed here. WSAEACCES (10013) Permission denied. An attempt was made to access a socket in a way forbidden by its access permissions. An example is using a broadcast address for sendto without broadcast permission being set using setsockopt (SO_BROADCAST). WSAEADDRINUSE (10048) Address already in use. Only one usage of each socket address (protocol/ip address/port) is normally permitted. This error occurs if an application attempts to bind a socket to an IP address/port that has already been used for an existing socket, or a socket that wasn't closed properly, or one that is still in the process of closing. For server applications that need to bind multiple sockets to the same port number, consider using setsockopt(so_reuseaddr). Client applications usually need not call bind at all - connect will choose an unused port automatically.
4 SYSTEMANROPET socket I systemanropet socket SOCKET socket (int af, int type, int protocol); har parametrarna samma syntax/semantik som i UNIX. If no error occurs, socket returns a descriptor referencing the new socket en variabel med datatypen SOCKET. Otherwise, a value of INVALID_SOCKET is returned, and a specific error code can be retrieved by calling WSAGetLastError. SYSTEMANROPET connect int connect ( SOCKET s, const struct sockaddr FAR* name, int namelen ); Syntax/semantik är ungefär som i UNIX. För en nätverksadress, sparas adressinformationen i en post av typen struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; Vid anrop av bind, accept och connect bör dock göras typkonvertering till (struct sockaddr *) För konvertering av portnumror till "network byte order" behövs makron htons såsom i UNIX.
5 Däremot returnerar inet_addr unsigned long inet_addr (const char FAR * cp); en binär ip-nummer enligt "network byte order", och därför behöver makron htonl INTE användas. Även i den symboliska konstanten INADDR_ANY är ip-numrets 4 byte i "network byte order" till åtskillnad från UNIX. The value returned is a number suitable for use as an Internet address. All Internet addresses are returned in IP's network order (bytes ordered from left to right). Systemanropet gethostbyname struct hostent FAR * gethostbyname(const char FAR * name); och posttypen struct hostent struct hostent { char FAR * h_name; char FAR * FAR * h_aliases; short h_addrtype; short h_length; char FAR * FAR * h_addr_list; }; har samma syntax/semantik som i UNIX, dvs. h_length is the length, in bytes, of each address The macro h_addr is defined to be h_addr_list[0] SYSTEMANROPEN bind, listen, accept och select Syntax/semantik är ungefär som i UNIX även för dessa systemanrop.
6 "socket"-kommunikation För "socket"-kommunikation kan användas systemanropen - send, sendto - recv, recvfrom med ungefär samma syntax/semantik som i UNIX. Däremot duger INTE read och write, eftersom en SOCKET-variabel INTE kan användas som en fildeskriptor i Windows. "socket"-kommunikation avslutas med shutdown såsom i UNIX, men en SOCKETvariabel stängs med int closesocket(socket s); This function closes a socket. More precisely, it releases the socket descriptor s, so that further references to s will fail with the error WSAENOTSOCK. PRAKTISK WINSOCK-PROGRAMMERING Med Winsock-programmering kan både förbindelse-orienterad (TCP-protokollet) och förbindelselös (UDP-protokollet) "socket"-kommunikation programmeras. Winsock-programmeringen är dock underställd Windows-programmeringen, vars processhantering skiljer sig från UNIX och där signalhanteringen helt saknas. I Windows är processklyvning inte möjlig. Däremot kan en applikation skapa flera s.k. exekveringstrådar (eng. "threads"). Motsvarigheten till till signaleringen i UNIX är det s.k. asynkrona funktionstillståndet i Winsock API (eng. "Asynchronous mode"). Detta asynkrona funktionstillstånd bygger på operationer, som aktiveras av meddelanden (eng. "messages") skickade mellan olika Windows-objekt. Funktionerna i det asynkrona funktionstillståndet har namn som börjar med "WSAAsync", t.ex. "WSAAsyncGetHostByName" den asynkrona motsvarigheten till "gethostbyname" (se t.ex. "help"-filen om Winsock version 2.0). Praktisk Winsock-programmering förutsätter således någon Windowsprogrammeringsmiljö. En s.k. konsolapplikation eller en visuell miljö, som gömmer de svårhanterliga "Windows API"-funktionerna bakom lätthanterliga grafiska objekt ger programmeraren möjlighet att fokusera sin uppmärksamhet på själva Winsockprogrammeringen.
7 BILAGA: The new API functions for Windows Sockets 2. Data Transport Functions Function WSAAccept 1 WSACloseEvent WSAConnect 1 WSACreateEvent WSADuplicateSocket WSAEnumNetworkEvents WSAEnumProtocols WSAEventSelect WSAGetOverlappedResult WSAGetQOSByName WSAHton l WSAHtons WSAIoctl1 WSAJoinLeaf 1 WSANtohl WSANtohs WSARecv1 WSARecvDisconnect WSARecvFrom 1 WSAResetEvent WSASend1 WSASendDisconnect WSASendTo 1 WSASetEvent WSASocket WSAWaitForMultipleEvents 1 Description An extended version of accept which allows for conditional acceptance and socket grouping. Destroys an event object. An extended version of connect which allows for exchange of connect data and QOS specification. Creates an event object. Creates a new socket descriptor for a shared socket. Discovers occurrences of network events. Retrieves information about each available protocol. Associates network events with an event object. Gets completion status of overlapped operation. Supplies QOS parameters based on a well-known service name. Extended version of htonl. Extended version of htons. Overlapped-capable version of ioctlsocket. Joins a leaf node into a multipoint session. Extended version of ntohl. Extended version of ntohs. An extended version of recv which accommodates scatter/gather I/O, overlapped sockets, and provides the flags parameter as IN OUT. Terminates reception on a socket and retrieves the disconnect data, if the socket is connection-oriented. An extended version of recvfrom which accommodates scatter/gather I/O, overlapped sockets, and provides the flags parameter as IN OUT. Resets an event object. An extended version of send which accommodates scatter/gather I/O and overlapped sockets. Initiates termination of a socket connection and optionally sends disconnect data. An extended version of sendto which accommodates scatter/gather I/O and overlapped sockets. Sets an event object. An extended version of socket which takes a WSAPROTOCOL_INFO structure as input and allows overlapped sockets to be created. Also allows socket groups to be formed. Blocks on multiple event objects. 1 The routine can block if acting on a blocking socket.