410 likes | 416 Views
Learn to create peer-to-peer and client/server apps using Windows Sockets API, essential for seamless network communication in Windows environment. Understand socket functions, initialization, and binding for streamlined development.
E N D
Chapter 12 Windows Sockets andNetwork Programming
OBJECTIVES • Upon completion of this chapter, you will be able to: • Understand the basic Windows Sockets API • Address portability issues between Berkeley and Windows Sockets • Use Windows Sockets over TCP/IP for peer-to-peer and client/server applications • Consider changes introduced by Windows Sockets 2 • See how the Service Registration APOI provides protocol transparency
WINDOWS SOCKETS (1 of 2) • An extension of the Berkeley Sockets API • Into the Windows environment • Porting of code already written for Berkeley Sockets • Windows stations easily integrated into TCP/IP networks • Exceptions when sockets treated as file descriptors • Under UNIX • Also, extended functions with WSA prefix
WINDOWS SOCKETS (2 of 2) • Functions that manipulate files also work with sockets read() ioctl() write() close() • Behave like overlapped Windows file handles • Other network communication options • Named pipes • Remote Procedure Calls
INITIALIZE THE WinSock DLL (1 of 2) • int WSAStartup( WORD wVersionRequired, LPWSADATA lpWSAData);
INITIALIZE THE WinSock DLL (2 of 2) • wVersionRequired • Indicates the highest version of the WinSock DLL you need • Returns a non-zero value if the DLL cannot support the version you want • Low byte specifies the major version • High byte specifies the minor version • 0x0101 version 1.1 • lpWSAData points to a WSADATA structure that returns information on the configuration of the DLL • WSAGetLastError() for error number
ALLOCATE A SOCKET (1 of 3) • Sockets are analogous to handles • A communication channel • Call socket() to create (or open) a socket • Actually a HANDLE
ALLOCATE A SOCKET (2 of 3) • Server: “Listening socket” for client connection requests typedef unsigned int SOCKET; SOCKET socket(int af, int type, int protocol);
ALLOCATE A SOCKET (3 of 3) • af denotes the address family • PF_INET or AF_INET designates the Internet protocol • type specifies connection-oriented (SOCK_STREAM)or datagram communications (SOCK_DGRAM) • protocol unnecessary for TCP/IP • Use 0 • socket returns INVALID_SOCKET upon failure
BIND (1 of 3) • Next, bind the socket to its address and service endpoint int bind ( SOCKET s, const struct sockaddr *saddr, int namelen); • s is an “unbound” SOCKET returned by socket() • saddr specifies the address family and protocol-specific information • namelen is sizeof(sockaddr) • Returns SOCKET_ERROR in case of error
BIND (2 of 3) • SOCKADDR structure struct sockaddr { u_short sa_family; char sa_data[14]; }; typedef struct sockaddr SOCKADDR, *PSPOCKADDR;
BIND (3 of 3) • sa_data is protocol-specific • TCP/IP sockaddr_in: struct sockaddr_in { short sin_family; // AF_INET u_short sin_port; struct in_addr sin_addr; //4-byte IP addr char sin zero [8]; }; typedef struct sockaddr_in SOCKADDR_IN, *PSOCKADDR_IN;
BIND CONSIDERATIONS • List of hosts (mapped to IP addresses) can be found in %SystemRoot%\system32\drivers\etc\hosts • List of Services(mapped to services) can be found in %SystemRoot%\system32\drivers\etc\services • If you bind to a specific IP address, you can only receive incoming packets over that IP address • If you have more than one IP address, bind to hotnl(INADDR_ANY) “host to network long”
BIND SETUP EXAMPLE (1 of 3) • BOOL WINAPI WNetGetHostAddress( • LPCSTR lpszHost, • LPCSTR lpszService, • LPCSTR lpszProto, • LPSOCKADDR lpAddr) • /* Fill in a SOCKADDR using host, protocol, • service */ • { • LPHOSTENT lpHost; • LPSERVENT lpServ; • SOCKADDR_IN sin; • ZeroMemory(&sin, sizeof(sin));
BIND SETUP EXAMPLE (2 of 3) • sin.sin_family = PF_INET; • sin.sin_addr.s_addr = htonl(INADDR_ANY); • if(lpszHost != NULL) • { lpHost = gethostbyname(lpszHost); • if(lpHost != NULL) • { CopyMemory(&sin.sin_addr, lpHost->h_addr_list[0], lpHost->h_length); • } • } • lpServ = getservbyname(lpszService, lpszProto);
BIND SETUP EXAMPLE (3 of 3) • if(lpServ != NULL) • { sin.sin_port = lpServ->s_port; • ZeroMemory(sin.sin_zero, • sizeof(sin.sin_zero)); • CopyMemory(lpAddr, &sin, sizeof(SOCKADDR)); • return TRUE; • /* lpAddr is now ready for bind() */ • } • return FALSE; • } • The address returned by WNetGetHostAddress() can be passed directly to the bind() function
listen () • listen() makes server available for client connection • Socket goes from “bound” to “listening” state int listen(SOCKET s, int nQueueSize); • nQueueSize indicates the number of connection requests you are willing to have queued at the socket • Up to SOMAXCON (5 for 1.1, “unlimited” in 2.0)
accept () (1 of 2) • The call to listen() places the socket into the listening state • The server application calls accept() • Returning a “connected socket” • accept() blocks until a client request for a connection arrives • accept() return value gives the server a new socket for exchanging data
accept () (2 of 2) • SOCKET accept( • SOCKET s, • /* Listening socket */ • LPSOCKADDR lpAddr, • /* Find client details here */ • LPINT lpnAddrLen • /* Length of the returned structure */ );
THE CLIENT SIDE (1 of 2) • A client station wishing to connect to a server must also create a socket by calling socket() • If it is not bound by an address, Windows Sockets will assign it a unique address to use for the duration of the connection
THE CLIENT SIDE (2 of 2) int connect( SOCKET s, LPSOCKADDR lpName, int nNameLen); • lpName points to a SOCKADDR structure designating the server machine name and port address
EXCHANGE OF DATA (1 of 2) • Partner stations exchange data using send() and recv() • send() and recv() have identical arguments: int send ( int recv ( SOCKET s, SOCKET s, LPSTR lpBuffer, LPSTR lpBuffer, int nBufferLen, int nBufferLen, int nFlags); int nFlags);
EXCHANGE OF DATA (2 of 2) • nFlags == MSG_OOB indicates urgency • OOB for out-of-band • MSG_PEEK can be used to peek at the data without removing it • These are standard Berkeley Sockets calls • But read() and write() are more common under UNIX • Not atomic or message oriented • Loop until full message is received • Or sent, although incomplete send() is rare
DATAGRAM SERVICE (1 of 2) • Stations send and receive data using sendto() and recvfrom() • Take the same arguments as send() and recv(), but add two to designate the partner station int sendto ( int recvfrom ( SOCKET s, SOCKET s, LPSTR lpBuffer, LPSTR lpBuffer, int nBufferLen, int nBufferLen, int nFlags, int nFlags, LPSOCKADDR lpAddr, LPSOCKADDR lpAddr, int nAddrLen); LPINT pnAddrLen);
DATAGRAM SERVICE (2 of 2) • With datagrams, the nFlags argument cannot be MSG_OOB • You cannot send or receive urgent data
CLOSING A SOCKET • In standard Berkeley Sockets, call close() • In Windows Sockets call void closesocket(SOCKET s); • For connection-oriented communications, the server side of the exchange closes the socket created by accept() • Not the one returned by socket() • Only when the server goes out of service should it close the listening socket • Finally, call void WSACleanup(void); • To break your connection to WSOCK32.DLL • This function is also non-portable
SOCKETS SUMMARY (1 of 2) • Connection Oriented Service • Server Client • socket() socket() • bind() connect() • listen() • accept() • send()/recv() • sendto()/recvfrom() • closesocket() closesocket()
SOCKETS SUMMARY (2 of 2) • Connectionless (Datagram) • Server Client • socket() socket() • listen() connect() • send()/recv() • sendto()/recvfrom() • closesocket() closesocket()
BERKELEY vs WINDOWS SOCKETS • Standard Berkeley Sockets calls will port to Windows Sockets, with these exceptions: • You must call WSAStartup() to initialize the sockets DLL • Though you can use UNIX-style read() and _write() to receive and send data, you must first convert the Windows socket to an operating system handle by calling _open_osfhandle() • In Sockets 1.1, you also have to call setsockopt() to force sockets to be opened as non-overlapped handles • You must use closesocket() (which is not portable), rather than close() (which is), to close a socket • You must call WSACleanup() to shut down the DLL
OVERLAPPED I/O WITH WINDOWS SOCKETS (1 of 2) • In WinSock 1.1, Windows opens sockets as overlapped file handles • You can pass a socket to ReadFile() or WriteFile() without modification • Wait for an operation to complete by tying it to an event handle, and call WaitForSingleObject() WaitForMultipleObjects() or MsgWaitForMultipleObjects
OVERLAPPED I/O WITH WINDOWS SOCKETS (2 of 2) • Use I/O completion routines with ReadFileEx() / WriteFileEx() and the extended wait functions WaitForSingleObjectEx(), WaitForMultipleObjectsEx(), and SleepEx() • Use an I/O completion port with ReadFile() / WriteFile(), CreateIoCompletionPort(), and GetQueuedCompletionStatus()
WINDOWS SOCKETS 2 (1 of 2) • Windows Sockets 2, available in NT 4.0, adds several areas of functionality • Note: Use 1.1 for interoperability reasons • Standardized support for overlapped I/O • Scatter/gather I/O • Sending and receiving from non-contiguous buffers in memory
WINDOWS SOCKETS 2 (2 of 2) • The ability to request quality of service from the Sockets support layer • Speed and reliability of transmission • The ability to organize sockets into groups • The quality of service of a socket group can be configured • It does not have to be done on a socket-by-socket basis • The sockets belonging to a group can be prioritized • Piggybacking of data onto connection requests • Multipoint connections (conference calls)
STANDARDIZATION OFOVERLAPPED I/O (1 of 2) • The most important addition to Windows Sockets 2 is the standardization of overlapped I/O • Sockets are no longer created automatically as overlapped file handles • socket() will create a non-overlapped handle • To create an overlapped socket, call WSASocket() and explicitly ask for one
STANDARDIZATION OFOVERLAPPED I/O (2 of 2) SOCKET WSAAPI WSASocket( int iAddressFamily, int iSocketType, int iProtocol, LPWSAPROTOCOL_INFO lpProtocolInfo, GROUP g, DWORD dwFlags);
SCATTER/GATHER I/O (1 of 4) • WinSock 2 adds the ability to collect and distribute data for transmission or reception from non-contiguous memory buffers typedef struct WSABUF { u_long len; char *buf; } WSABUF, *LPWSABUF;
SCATTER/GATHER I/O (2 of 4) • buf points to the data • len is the number of bytes in this particular buffer • WSASend(), WSARecv(), WSASendTo(), and WSARecvFrom() take an array of WSABUF structures
SCATTER/GATHER I/O (3 of 4) int WSARecv( SOCKET s, LPWSABUF lpRecvBuffers, DWORD dwBuffers, LPDWORD lpdwBytesReceived, LPDWORD lpdwFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
SCATTER/GATHER I/O (4 of 4) • lpRecvBuffers points to an array of WSABUF structures • dwBuffers is the number of structures in the array • When data arrives, the WinSock 2 drivers disperse it among the buffers passed
LAB B–1 (1 of 2) • Use Windows Sockets to connect clients (the client program) to a “command line server” • The clients take a command line and send it to a known server for execution • The server returns the results to the client over the socket • The solution consists of two components: • Client.c • Run Client.exe in its own window • Server.c
LAB B–1 (2 of 2) • Server.c is built as Server.exe and runs in its own window or is controlled with the job management commands from Module 5 • Place the commands to be executed in the same directory as Server.exe • The header file, ClntSrvr.h, contains definitions used in the various programs, such as the message format • WSOCK32.LIB must be included when linking • Challenge: Extend server to set up service name in services file and client finds it with WNetGetHostAddress