Winsock Networking Tutorial (C

++)
© 2010 by Thomas Bleeker (MadWizard)

Networking introduction
First I will give you an introduction to basic networking principles and terms. Anyone with internet acc ess will have some knowledge about networks, servers, c lients, but to ensure you know enough to program with it I've inc luded this chapter. You won't need all the details mentioned here when programming winsock, but it's good to know something about the underlying techniques.

1. Ne tworks and protocols
You probably already know what a network is, it's a c ollec tion of computers c onnected to each other so they c an exc hange data. There are several types of networks, suc h as LANs (Loc al Area Network), WANs (Wide Area Network) and of c ourse the internet. To ensure that all traffic is going smoothly, networks rely on protocols:
Protocol A protocol is a set of rules describing the format in which data is transmitted over a network.

As stated in the information box above, a protocol desc ribes how to c ommunic ate over a network. It c an be c ompared with a human language: at the lowest level nearly everyone c an make and hear sounds (compare: elec tronic signals) but people won't understand eac h other unless they speak a ac c ording to a specific language they both understand (c ompare: protocol).

2. Ethe rne t
Networks rely on several protocol layers, eac h one having its own task in the communic ation proc ess. A very c ommonly used configuration is the ethernet LAN with TCP/IP. In ethernet LANs, c omputers c an be connec ted using c oaxial, twisted pair (UTP) or optic fiber c ables. Nowadays, for most networks, UTP c ables are used. WANs and the internet (partly a combination of many WANs) use many of the tec hniques used in ethernet LANs, so I will disc uss ethernet LAN technology first. MAC The lowest layer of ethernet is the hardware level, c alled the Media Access Layer, or MAC for short. This layer can be a network c ard, for example, whic h contains the serial network interface and c ontroller that take care of c onverting the raw data into electronic signals and sending it to the right plac e. Pac kage that are sent over a network of c ourse need to reac h their destination. So there has to be some kind of addressing. Various levels of the ethernet interfac e have different addressing methods, as you will see later. At the lowest MAC level, addressing is done with MAC numbers.
MAC number 48-bit identifier that is hardcoded into each network interface unit. The allocation of these numbers is done by the IEEE Registration Authority so each ethernet chip has a world wide unique number (that is, if the manufacturer didn't mess up :). MAC numbers are often noted as colon-separated hex numbers: 14:74:A0:17:95:D7.

To send a pac ket to another network interfac e, the pac ket needs to inc lude its MAC number. LANs use a very simple method to send the packets to the right interfac e: broadcasting. This means that your network card just shouts the pac kage to every other interfac e it c an reac h. Eac h
Winsock C++ programming tutorial Page 1 / 46

Networking introduction - MadWizard.org

rec eiving interface looks at the destination MAC number of the packet, and only buffers it if matc hes its own MAC number. While this method is easy to implement and quite effec tive on LANs, bigger networks (WANs, internet) don't use this method for obvious reasons; you wouldn't want everyone on the internet to send pac kets to everyone else on the internet. WANs use better routing mec hanisms, which I won't discuss here. Just remember that at the lowest level, addressing is done with MAC numbers. Ethernet pac kets also inc lude a CRC and error detection. IP Just above the hardware level is the IP level. IP simply stands for Internet Protocol. Just like the MAC layer, IP too has its own way of addressing:
IP number The numbers used to address at the IP level of the network interface. IPv4, the version most widely used uses 32-bit values, noted in the well known dotted format: 209.217.52.4. Unlike MAC numbers, IP numbers are not hardcoded into the hardware, they are assigned to it at software level.

IP numbers shouldn't be something strange to you. The internet uses them to uniquely identify a specific computer. IP addresses can be assigned to a network interfac e using software. Doing this assoc iates the IP number with the MAC address of the network interfac e. To address using IP numbers, the associated MAC number needs to be resolved. This is done with the ARP (Address Resolution Protocol). Eac h host maintains a list with pairs of IP and MAC numbers. If an IP is used without a matc hing MAC number, the host sends out a query pac ket to the rest of the LAN. If any of the other computers in the LAN rec ognize their IP number, it sends bac k the c orresponding MAC number. If no matching MAC number c an be found the pac ket is sent to the gateway, a c omputer that forwards pac kages to external networks. The IP to MAC c onversion is ac tually done at the data link layer (MAC layer) The IP protocol adds the sourc e and destination address (IP numbers) to the pac ket, as well as some other pac kage properties suc h as the TTL hops (time to live hops), the protocol version used, header c hecksum, sequence c ount and some more fields. They are not important to us so I won't explain them in detail. TCP The next layer is the TCP layer (or alternatively, the UDP layer). This layer is very c lose to the network applic ation and deals with many things. As final addition to the addressing, TCP adds a port number to the package:
Port number While IP numbers are used to address a specific computer or network device, port numbers are used to identify which process running on that device should receive the package. Port numbers are 16-bit, and thus limited to 65536 numbers. A process can register to receive packets sent to a specific port number ('listening'). A notation often used when addressing a port number on a device is 'IP:portnumber', eg. 209.217.52.4:80. Both sides of a connection use a port number, but not necessarily the same.

Many port numbers are WKP (Well Known Ports), that is they are c ommonly associated with a specific service. For example, the WWW uses port 80 by default, FTP uses port 21, e-mail uses 25 (SMTP) and 110 (POP). Although these are the ports usually used for those servic es, nobody
Winsock C++ programming tutorial Page 2 / 46

Networking introduction - MadWizard.org

prevents you from using different ports. However, it's a good practic e to use port numbers higher than 1024 for other, c ustom servic es. While the IP layer doesn't c are about the succ ess of transmissions, TCP does. The TCP layer ensures data does arrive, and c orrectly. It also lets the receiver c ontrol the data flow, ie. the rec eiver can dec ide when to rec eive data. If a package is lost during the way to its destination, TCP resends the pac kage. TCP also reorders the pac kages if they arrive in an order different from the original order. This makes the programmer's life easy as it c an safely assume the data that is sent is rec eived and in the right order. UDP, an alternative for TCP, does not have these features and cannot guarantee the arrival of pac kages. TCP is c onnection-oriented, and the best c hoic e for c ontinuous data streams. UDP on the other hand is c onnectionless, and packet oriented. I won't deal with UDP in this tutorial. Software Finally, above the TCP layer is the network software. In windows, your applic ation does not direc tly acc ess the TCP layer but uses the WinSock API. The software layer provides a very c onvenient way of dealing with networking. Thanks to all the underlying layers, you don't need to worry about packets, pac ket size, data corruption, resending of lost pac kets etc.

3. T he e the rne t inte rface stack

The image above shows the encapsulation of the eac h protoc ol in the ethernet interfac e stack. It all starts with the software layer, whic h has a piec e of data that it wants to send over the network. Even this data usually has a format (eg. HTTP, FTP protocols), although not shown in the image. The user data first gets a TCP header inc luding the source and destination port number. Then the IP header is added, c ontaining the sourc e and destination IP address. Finally the data link layer adds the ethernet header, which specifies the MAC numbers of the source and destination. This is the data that is ac tually sent over the wires. As you c an see there's a lot of overhead in an TCP/IP pac kage. The overhead c an be minimized by choosing a large enough data size for the pac kage. Luckily winsoc k will arrange this for you.
Winsock C++ programming tutorial Page 3 / 46

Networking introduction - MadWizard.org

Networking continued
Now that you know the basic layers of the network interfac e, I will c ontinue with some other principles conc erning hostnames, c onnec tions and software level protocols.
1 . DNS

DNS stands for Domain Name System, whic h ac c ounts for the conversion of hostnames to and from IP could numbers. Bec ause a hostname a IP numbers alternatively. website, its IP are not easy to of So remember (well not many are: at least), another more c onvenient naming system was c reated. Now, instead of an IP number, you use Examples is needed. hostnames if you madwizard.org, hostname like somepc.someuniversity.edu, www.google.com, etc . Anyone browsing the internet has used them. When c onnecting to enter a www.google.c om, it first needs to lookup the c orresponding IP number of google. This is where DNS c omes in. Your PC sends out a hostname lookup request to the DNS your provider has setup in its network. If the DNS c an resolve the hostname, it sends bac k the c orresponding IP to you. DNS are organized in a hierarc hical way, forwarding unresolvable hostnames to a DNS at a higher level, until the hostname is resolved.
2 . Conne c tions

TCP/IP is a c onnection-oriented protocol. The connec tion is always between two devices, and eac h side uses its own IP and port number. Usually, one side is c alled the client, the other side the server.

The c lient is the one that requests something, the server responses acc ordingly. For example, when opening a website, the browser is the c lient, the webserver is the server. The browser initiates the c onnection with the server and requests a spec ific resourc e. The server then sends bac k a response and the data requested. The server is c ontinually waiting for incoming c onnections. This is c alled listening, which is always done on a c ertain IP and port number. The c lient is only ac tive when necessary, as the client is always the initiator of a connection and the one that requests information. To create a connec tion, the c lient needs to know both the IP and port number the server is listening on. A connec tion is made to that server and hopefully ac cepted by the server. While c ommunication over a TCP/IP c onnection is two-way, many protoc ols (HTTP, FTP, etc ) let the c lient and server interac t in turn.
Winsock C++ programming tutorial Page 4 / 46

Networking introduction - MadWizard.org

Both the server and c lient side use an IP and port number, but the IP and port number of the server are usually fixed. The standard port for the WWW is 80 (using HTTP). Google for example, is a webserver that runs on port 80 and IP 216.239.39.101 (at the moment of writing). Eac h client (read: anyone google- ing :) connects to this IP and port. So the webserver c an have many connec tions on the same port. This is no problem, sinc e all traffic on that port is for the same process. On the c lient side, the port number doesn't matter. Any port c an be used. Some people think that the port number used in a c onnection needs to be the same on both sides. This is not true. Just open a website and quic kly run 'netstat - an' in a command line. You might see a line like this: TCP xxx.xxx.xxx.xxx:2894 216.239.39.101:80 ESTABLISHED xxx.xxx.xxx.xxx was my IP, 216.239.39.101 is google's IP. The number after the colon is the port number. As you c an see, the server side uses port 80, while the client uses a random (read: some free) port number like 2894. Each client connec tion needs a different port number on the c lient side, since every c onnection is associated with a different c lient.
Client The program that initiates the connection, and requests information. Server The program that listens for incoming connections, accepts them and responses according to the received requests. The IP and port number of the server need to be known by the client to connect to it.

3 . Pr otoc ols a ga in

In the previous chapters I have showed several protoc ols at the different levels of a network interfac e. The protocols I didn't discuss yet are the protocols that work at software level. Examples of these are HTTP, FTP, POP3, SMTP. Most of them work in a c lient-server way, ie. the client makes requests, the server responds. The exac t format of the requests and responses are desc ribed in these protoc ols. I won't discuss them further right now, but I will later when you know the winsock basic s to actually implement them.

Sockets and winsock
Winsock ('Windows Soc kets') is the Windows API that deals with networking. Many func tions are implemented in the same way as the Berkeley socket functions used in BSD Unix.
1 . Soc ke ts

So what's a soc ket?
Socket As explained in the previous chapter, you will work with two-way connections. The endpoints of this connection are the sockets. Both the client and the server have a socket. A socket is associated with a certain IP and port number.

Almost all winsoc k func tions operate on a soc ket, as it's your handle to the c onnection. Both sides of the c onnection use a socket, and they are not platform- spec ific (ie. a Windows and Unix
Winsock C++ programming tutorial Page 5 / 46

Sockets and winsock - MadWizard.org

mac hine c an talk to eac h other using soc kets). Soc kets are also two-way, data can be both sent and received on a socket. There are two common types for a socket, one is a streaming soc ket (SOCK_STREAM), the other is a datagram soc ket (SOCK_DGRAM). The streaming variant is designed for applications that need a reliable c onnection, often using continuous streams of data. The protoc ol used for this type of soc ket is TCP. I will only use this type in my tutorial as it's most c ommonly used for the well known protocols like HTTP, TCP, SMTP, POP3 etc. Datagram soc kets use UDP as underlying protocol, are c onnectionless, and have a maximum buffer size. They are intended for applications that send data in small pac kages and that do not require perfect reliability. Unlike streaming soc kets, datagram sockets do not guarantee data will reach its destination nor that it comes in the right order. Datagram sockets can be slightly faster and useful for applic ations like streaming audio or video, where reliability is not as high on the priority list as speed and latenc y. Where the reliability is required, streaming soc kets are used.
2 . Binding s oc k ets

Binding a socket means associating a specific address (IP & port number) with a given soc ket. This can be done manually using the bind function, but in some cases winsock will automatic ally bind the socket. This will bec ome clear in the next paragraphs.
3 . Conne c ting

The way you use a soc ket depends on whether you are on the client side or the server side. The client side initiates a c onnection by creating a socket, and calling the connect function with the spec ified address information. Before the socket is connec ted, it is not bound yet to an IP or port number. Because the c lient side c an use any IP and port number for the connec tion with the server (provided that network the IP number is part of c an reach the network of the destination IP), often many useable c ombinations are possible. When c onnect is called, winsock will c hoose the IP and port number to use for the c onnection and bind the socket to it before ac tually c onnecting it. The port number c an be anything that is free at the moment, the IP number needs a bit more c are. PCs may have more than one IP. For example, a PC connec ted to both the internet and a local network has at least three IPs (the external IP for use with the internet, the local network IP (192.168.x.x, 10.0.x.x etc .) and the loop bac k address (127.0.0.1)). Here, it does matter to whic h IP the soc ket is bound as it also determines the network you are using for the c onnection. If you want to connec t to the local PC 192.168.0.4, you c annot do that using the network of your internet provider, as that IP is never used in the internet and will not be found. So you would have to bind the soc ket to your IP in the same network (192.168.0.1 for example). Similarly, when you bind the socket to the local loop bac k address (127.0.0.1), you can only c onnect to that same address, as no other address exist in that 'network'. Fortunately, winsock will c hoose a local IP it c an use for the IP you want to c onnec t to automatic ally. Nothing stops you from binding the soc ket yourself, but remember that you need to take the situations above in c onsideration. Note that the bind func tion gives the user the option to set the IP or port number to zero. In this
Winsock C++ programming tutorial Page 6 / 46

Sockets and winsock - MadWizard.org

case, zero means 'let winsock c hoose something for me'. This is useful when you do want to connec t using a spec ific IP on the client side, but do not c are about the port number used.
4 . Lis tening

Things are different on the server side. A server has to wait for incoming c onnections and c lients will need to know both the IP and port number of the server to be able to c onnect to it. To make things easy, servers almost always use a fixed port number (often the default port number for the used protocol). Waiting for incoming connec tions on a specified address is called listening:
Listening A socket is listening when it is in a state where it will 'listen' for incoming connections. Usually, this is done on a socket bound to a specific address known to the client.

As you c an see from the definition above, sockets are often bound to an address before putting it in the listening state. When the port number of this address is set to a fixed number, the server will listen for inc oming c onnections on that port number spec ific ally. For example, port 80 (the default for HTTP) is listened on by most web servers. The soc ket c an be bound to a spec ific IP as well but when zero is c hosen it will listen on any addresses available, effec tively allowing connec tions from all networks. It may be set to a fixed IP, for example the IP of the loc al network interfac e, so c omputers from the local network can c onnect to the server but not the ones connec ted via the internet. When a client requests a c onnection to a listening server, the server will ac c ept it (or not) and spawn another socket whic h will be the endpoint of the c onnection. This way the listening socket is not used for any data transfer on the c onnection and c an c ontinue listening for more inc omming c onnec tions.
5 . Conne c tions : a n ex a m ple

Here's a graphic al example of a webserver that can handle multiple c onnections. 1. The server socket is created

The server c reates a new socket. When it's just c reated it is not yet bound to an IP or port number. 2. The server socket is bound
Winsock C++ programming tutorial Page 7 / 46

Sockets and winsock - MadWizard.org

Bec ause the server is a webserver, it will be bound to port number 80, the default for HTTP. However the IP number is set to zero, indic ating the server is willing to rec ieve incomming connec tions from all IPs available for the mac hine it runs on. In this example, we assume the server has three IPs, one external (216.239.39.101), one internal (192.168.0.8) and of c ourse the loop back address (127.0.0.1). 3. The server is listening

After the socket is bound, it is put into the listening state, waiting for incomming connec tions on port 80. 4. A client creates a socket

Assume a client in the same loc al network as the server (192.168.x.x) wants to request a webpage from the server. To do the data transfer it needs a socket so it creates one. 5. The client socket tries to connect

madwizard.org/programming/…/1 Winsock C++ programming tutorial

Page 8 / 46

8/19

7/23/2010

Networking introduction - MadWizard.org

The client socket is left unbound and tries to connec t to the webserver. 6. The server accepts the request

The listening soc ket sees some client wants to make a c onnection. It acc epts it by creating a new socket (on the bottom right) bound to the one of the IPs of itself whic h can be reached by the c lient (ie. they are in the same network, being 192.168.x.x) and the server port (80). From this point, the c lient socket and the server c onnection socket just c reated will do the data transfers, while the listening socket will keep listening for other c onnections. Note that the c lient socket is now bound to an IP and port sinc e it's c onnected. The dotted gray line shows the separation of the c lient and server side. 7. Another client connects

Winsock C++ programming tutorial

Page 9 / 46

Sockets and winsock - MadWizard.org

If another client (from the external network) c onnects, the server will again create a new soc ket to deal with the second c onnection. Note that the IP the socket on the server side is bound to is different than the one from the first c onnection. This is possible bec ause the listening server socket was not bound to any IP. If it had been bound to 192.168.0.8, the sec ond c onnection would not be possible.
6 . Bloc k ing

The original func tions in the Berkeley unix implementation of sockets were bloc king functions. This means that they will just wait when the operation requested cannot be completed immediately. For example, when c onnecting to a server using the connect function, it did not return until the connec tion had been made (or failed), thus making the program hang for a while. This is not really a problem when dealing with a single c onnection using a c onsole mode applic ation but in the Windows environment, this behavior is rarely ac ceptable. Any program with a window has a window procedure that has to be kept running. Stalling it would delay user input, window painting, notific ations, and any other messages resulting in an application that seems to be hanging while it's using socket functions. To deal with this problem, winsoc k can set sockets into blocking or non-blocking mode. The former (bloc king mode) is the original way of using sockets, ie. not returning from the API before the operation has finished (it will literally block the applic ation). The latter (non-blocking mode) is the mode you usually use when dealing with a real windows applic ation (ie. not a console application). When c alling a function on a socket that is in non-blocking mode, the function will always return as soon as possible, even when the operation to be performed could not be completed immediately. Instead, a notific ation of some sort will be sent to the program when the operation is finished, allowing the program to execute in the normal manner while the operation is unfinished. Winsock provides several methods of notific ation for non-blocking sockets, including window messages and event objects. These methods will be disc ussed in detail later, for now just remember there differenc e between blocking and non-blocking.
7 . W insoc k ve r sions

The most c ommonly used winsock version is version 2.x, usually just c alled winsock 2 as there are only minor differenc es. The latest version before version 2 was version 1.1. Some people say you should use this version for compatibility reasons, as Windows 95 and NT 3 only ship version 1.1. However, all later windows versions (98, ME, NT4, 2000 and XP) have version 2 by default and for Windows 95 an update is available. So I recommend you just start with winsoc k 2, it adds a lot of nic e features and windows mac hines without winsock 2 are getting rare.
Winsock C++ programming tutorial Page 10 / 46

Sockets and winsock - MadWizard.org

The two major versions of winsock reside in two different DLLs, wsock32.dll and ws2_32.dll, being version 1.1 and version 2.x respec tively. The libraries to use are wsock32.lib and ws2_32.lib. The MASM32 pac kage has most winsock c onstants in its windows.inc, for C++ programs inc luding windows.h suffices, it will inc lude the winsock 2 definitions if the _WIN32_WINNT c onstant is at least 0x400 (NT version 4). The winsock 2 API inc ludes the full 1.1 API (with some minor c hanges), wsoc k32.dll is even just a wrapper for the ac tual winsock ws2_32.dll. This tutorial will assume you are using winsoc k 2.
8 . W insoc k ar c hite c tur e

Winsock provides two interfaces, the Applic ation Programming Interfac e (API) and the Servic e Provider Interfac e (SPI). This tutorial is about the API, it c ontains all the functions you need to communcate using the well-known protocols. The SPI is an interface to add Data Transport Providers (like TCP/IP or IPX/SPX) or Name Spac e Service Providers (like DNS). These extensions are transparent to the user of the API.

Basic winsock functions
In this c hapter of the winsock tutorial, I will show you the basic winsoc k functions that operate on sockets. It is important to remember that this c hapter is only an introduc tion to the socket functions, so you will be able to follow the next tutorials. Do not start coding immediately after you've read this c hapter, the next c hapters are just as important. The basic functionality of eac h function is relatively simple, but things like the bloc king mode make it more complic ated than it looks at first sight. The next c hapters will c over the details, but first you need to be familiar with the functions. This c hapter is quite long and you might not remember everything but that's okay. Just read it carefully so you know what I'm talking about in the next c hapters, you c an always look bac k here and use it as a quic k reference.
1 . W SASta r tup & W SACle a nup

int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData); int WSACleanup(); Before c alling any winsoc k function, you need to initialize the winsock library. This is done with WSAStartup. It takes two parameters: wVersionRequested Highest version of Windows Soc kets support that the c aller can use. The high-order byte spec ifies the minor version (revision) number; the low-order byte specifies the major version number. lpWSAData Pointer to the WSADATA data struc ture that is to rec eive details of the Windows Sockets implementation.
Winsock C++ programming tutorial Page 11 / 46

Basic winsock functions - MadWizard.org

As explained in the introduc tion, I will use winsoc k 2. This means you need to set the low byte of wVersionRequested to 2, the high byte can be zero (the revision number is not important). The WSADATA struc ture specified with the lpWSAData parameter will receive some information about the winsoc k version installed. The function returns zero if it suc c eeded, otherwise you c an call WSAGetLastError to see what went wrong. WSAGetLastError is the winsock equivalent of the win32 APIs GetLastError, it retrieves the c ode of the last oc curred error. It is important to note that you might not get the version you requested in

the wVersionRequestedparameter. This parameter specifies the highest winsoc k version your application *supports*, not 'requires'. Winsock will try hard to give you the version you requested but if that is not possible, it uses a lower version. This version is available after the c all, in the wVersion member of the WSADATA structure. You should check this version after the call to see if you really got the winsock version you wanted. There is also a member called wHighVersion that gives the highest winsock version supported by the system. In short: wVersionRequested parameter: The highest winsock version your applic ation supports. wHighVersion in WSADATA: The highest winsoc k version the system supports. wVersion in WSADATA: min(wVersionRequested, wHighVersion). Eac h c all to WSAStartup has to match a call to WSACleanup, whic h c leans up the winsoc k library. Although useless, WSAStartup may be called more than onc e, as long as WSACleanup is called the same number of times. An example of initializing and c leaning up winsoc k:
const int iReqWinsockVer = 2; WSADATA wsaData; if (WSAStartup(MAKEWORD(iReqWinsockVer,0), &wsaData)==0) { // Check if major version is at least iReqWinsockVer if (LOBYTE(wsaData.wVersion) >= iReqWinsockVer) { /* ------- Call winsock functions here ------- */ } else { // Required version not available } // Cleanup winsock if (WSACleanup()!=0) { // cleanup failed } } else { // } startup failed // Minimum winsock version required

2 . s ock e t

SOCKET socket(int af, int type, int protocol); The socket func tion c reates a new socket and returns a handle to it. The handle is of type SOCKET and is used by all functions that operate on the socket. The only invalid socket handle
Winsock C++ programming tutorial Page 12 / 46

Basic winsock functions - MadWizard.org

value is INVALID_SOCKET (defined as ~0), all other values are legal (this inc ludes the value zero!). Its parameters are: af The address family to use. Use AF_INET to use the address family of TCP & UDP. type The type of socket to c reate. Use SOCK_STREAM to c reate a streaming soc ket (using TCP), or SOCK_DGRAM to c reate a diagram soc ket (using UDP). For more information on socket types, see the previous c hapter. protocol The protoc ol to be used, this value depends on the address family. You c an spec ify IPPROTO_TCP here to c reate a TCP socket. The return value is a handle to the new soc ket, or INVALID_SOCKET if something went wrong. The socket function c an be used like this:
SOCKET hSocket; hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (hSocket==INVALID_SOCKET) { // error handling code }

3 . c los es ock e t

int closesocket(SOCKET s); Closesocket closes a socket. It returns zero if no error oc curs, SOCKET_ERROR otherwise. Eac h socket you created with socket has to be c losed with an appropriate c losesocket call. s Handle to the socket to be c losed. Do not use this soc ket handle after you c alled this func tion. The use of closesoc ket is pretty straightforward:
closesocket(hSocket);

However, in real situations some more operations are necessary to c lose the socket properly. This will be disc ussed later in the tutorial.
4 . s ock a ddr a nd byte or de r ing

Bec ause winsoc k was made to be c ompatible with several protocols including ones that might be added later (using the SPI) a general way of addressing has to be used. TCP/IP uses an IP and port number to spec ify an address, but other protocols might do it differently. If winsock forc ed a certain way of addressing, adding other protocols may not have been possible. The first version of winsoc k solved this with the sockaddr struc ture:
struct sockaddr { u_short sa_family; char sa_data[14]; };

Winsock C++ programming tutorial

Page 13 / 46

Basic winsock functions - MadWizard.org

In this struc ture, the first member (sa_family) specifies the address family the address is for. The data stored in the sa_data member can vary among different address families. We will only use the internet address family is (TCP/IP) the TCP/IP in this tutorial, of winsock has defined They a are struc ture sockaddr_in that version the sockaddr structure.

essentially the same structure, but the sec ond is obviously easier to manipulate.
struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; };

The last 8 bytes of the structure are not used but are padded (with sin_zero) to give the struc ture the right size (the same size as sockaddr). Before proceeding, it is important to know about the network byte order. In c ase you don't know, byte ordering is the order in which values that span multiple bytes are stored. For example, a 32bit integer value like 0x12345678 spans four 8- bit bytes. Intel x86 mac hines use the 'little-endian' order, whic h means the least significant byte is stored first. So the value 0x12345678 would be stored as the byte sequence 0x78, 0x56, 0x34, 0x12. Most machines that don't use little-endian use big-endian, which is exactly the opposite: the most signific ant byte is stored first. The same value would then be stored as 0x12, 0x34, 0x56, 0x78. Bec ause protocol data c an be transferred between mac hines with different byte ordering, a standard is needed to prevent the machines from interpreting the data the wrong way.
Network byte ordering Because protocols like TC P/IP have to work between different type of systems with different type of byte ordering, the standard is that values are stored inbig-endian format, also called network byte order. For example, a port number (which is a 16-bit number) like 12345 (0x3039) is stored with its most significant byte first (ie. first 0x30, then 0x39). A 32-bit IP address is stored in the same way, each part of the IP number is stored in one byte, and the first part is stored in the first byte. For example, 216.239.51.100 is stored as the byte sequence '216,239,51,100', in that order.

Apart from the sin_family value of sockaddr and sockaddr_in, whic h is not part of the protoc ol but tells winsoc k which address family to use, all the values in both structures have to be in network byte order. Winsock provides several functions to deal with the c onversion between the byte order of the local host and the network byte order:
// Convert a u_short from host to TCP/IP network byte order. u_short htons(u_short hostshort); // Convert a u_long from host to TCP/IP network byte order. u_long htonl(u_long hostlong); // Convert a u_long from TCP/IP network order to host byte order. u_short ntohs(u_short netshort); // Convert a u_long from TCP/IP network order to host byte order. u_long ntohl(u_long netlong);

You might question why we should need four API functions for suc h simple operations as swapping the bytes of a short or long (as that's enough to c onvert from little-endian (intel) to big-endian (network)). This is bec ause these APIs will work even if you are running your program on a mac hine with other byte ordering than an intel mac hine (that is, the APIs are platform independent), like Windows CE on a handheld using a big-endian processor. Whether you use
Winsock C++ programming tutorial Page 14 / 46

Basic winsock functions - MadWizard.org

these APIs or your own macros/functions is up to you. Just know that the API way is guaranteed to work on all systems. Bac k to the sockaddr_in structure, as said above, all members except for sin_family have to be in network byte order. For sin_family use AF_INET. sin_port is the port number of the address (16-bit), sin_addr is the IP address (32-bit), dec lared as an union to manipulate the full 32- bit word, the two 16-bit parts or each byte separately. sin_zero is not used. Here are several examples of initializing soc kaddr_in struc tures:
sockaddr_in sockAddr1, sockAddr2; // Set address family sockAddr1.sin_family = AF_INET; /* Convert port number 80 to network byte order and assign it to the right structure member. */ sockAddr1.sin_port = htons(80); /* inet_addr converts a string with an IP address in dotted format to a long value which is the IP in network byte order. sin_addr.S_un.S_addr specifies the long value in the address union */ sockAddr1.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // Set address of sockAddr2 by setting the 4 byte parts: sockAddr2.sin_addr.S_un.S_un_b.s_b1 = 127; sockAddr2.sin_addr.S_un.S_un_b.s_b2 = 0; sockAddr2.sin_addr.S_un.S_un_b.s_b3 = 0; sockAddr2.sin_addr.S_un.S_un_b.s_b4 = 1;

The inet_addr func tion in the example above c an c onvert an IP address in dotted string format to the appropriate 32- bit value in network byte order. There is also a func tion c alled inet_ntoa, whic h does exac tly the opposite. As a side note, winsoc k 2 does not require that the structure used to address a soc ket is the same size of soc kaddr, only that the first short is the address family and that the right structure size is passed to the functions using it. This allows new protocols to use larger structures. The sockaddr structure is provided for bac kwards c ompatibility. However, since we will only use TCP/IP in this tutorial, the soc kaddr_in structure c an be used perfec tly.
5 . c onne ct

int connect(SOCKET s, const struct sockaddr *name, int namelen); The connec t function connec ts a soc ket with a remote socket. This function is used on the c lient side of a c onnection, as you are the one initiating it. A short description of its parameters: s The unconnected socket you want to c onnect. name Pointer to a sockaddr structure that c ontains the name (address) of the remote socket to c onnect to. namelen Size of the struc ture pointed to by name. The first parameter s is the c lient soc ket used for the c onnection. For example, a socket you've just c reated with the socket func tion. The other two parameters, name and namelen are used
Winsock C++ programming tutorial Page 15 / 46

Basic winsock functions - MadWizard.org

to address the remote socket (the server soc ket that is listening for inc oming c onnections). This is done by using a sockaddr structure (or soc kaddr_in for TCP/IP), as described in the previous section. A possible use of this function is connecting to a webserver to request a page. To address the server, you can use sockaddr_in structure and fill it with the server's IP and port number. You might wonder how you get the IP of a hostname like www.madwizard.org, I will show you how to do that later. For now, just assume you know the server's IP number. Assuming a webserver is running on a loc al network PC with IP number 192.168.0.5, using the default HTTP port 80, this would be the code to c onnect to the server:
/* This code assumes a socket has been created and its handle is stored in a variable called hSocket */ sockaddr_in sockAddr; sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(80); sockAddr.sin_addr.S_un.S_addr = inet_addr("192.168.0.5"); // Connect to the server if (connect(hSocket, (sockaddr*)(&sockAddr), sizeof(sockAddr))!=0) { // error handling code } /* Note: the (sockaddr*) cast is necessary because connect requires a sockaddr type variable and the sockAddr variable is of the sockaddr_in type. It is safe to cast it since they have the same structure, but the compiler naturally sees them as different types. */

6 . bind

int bind(SOCKET s, const struct sockaddr *name, int namelen); Binding a socket has been explained in the previous chapter. By binding a socket you assign an address to a socket. Bind's parameters are: s The unbound socket you want to bind. name Pointer to a sockaddr structure that contains the address to assign to the socket. namelen Size of the struc ture pointed to by name. For TCP/IP, the sockadrr_in structure can be used as usually. Let's look at an example first:
sockaddr_in sockAddr; sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(80); sockAddr.sin_addr.S_un.S_addr = INADDR_ANY; // use default // Bind socket to port 80 if (bind(hSocket, (sockaddr*)(&sockAddr), sizeof(sockAddr))!=0) { // error handling code }

As you c an see, a soc kaddr_in struc ture is filled with the necessary information. The address family is AF_INET for TCP/IP. In the example, we bind the socket to port number 80, but not to
Winsock C++ programming tutorial Page 16 / 46

Basic winsock functions - MadWizard.org

an IP number. By specifying the INADDR_ANY value as IP address, winsock will choose an address for you. This can be very useful for PCs with multiple network adapters (and thus multiple IPs). If you do want to bind to a specific IP, just convert the IP to a DWORD in network byte order and put it in the structure. Something similar is possible with the port number; when you spec ify 0 as the port number winsock will assign a unique port with a value between 1024 and 5000. However, most of the time you want to bind to a spec ific port number. Binding is usually done before putting the socket in a listening state, to make the socket listen on the right port number (and optionally an IP number). Although you c an also bind a soc ket before connec ting it, this is not commonly done because the address of the socket on the c lient side is not important most of the time.
7 . lis te n

int listen(SOCKET s, int backlog); The listen function puts a socket in the listening state, that is it will be listening for inc oming connec tions. It has two parameters: s The bound, unconnected soc ket you want to set into the listening state. backlog Maximum length of the queue of pending c onnections. The bac klog parameter can be set to specify the length of the queue of pending c onnections that have not yet been ac cepted. Usually, you c an use the default value SOMAXCONN, allowing the underlying service provider to c hoose a reasonable value. Before listen is called, the soc ket must have been bound to an address, as shown in the previous section. For example, if you bind a socket to port 80 and then c all listen on the socket, all inc oming connections on port 80 will be routed to your applic ation. To ac tually acc ept the connec tion, another function c alled acceptis available, it will be explained in the next sec tion. The following c ode snippet shows how to c all the listen function on a socket that has been bound already:
/* This code assumes the socket specified by hSocket is bound with the bind function */ if (listen(hSocket, SOMAXCONN)!=0) { // error handling code }

8 . a c ce pt

SOCKET accept(SOCKET s, struct sockaddr *addr, int *addrlen); When the socket is in the listening state and an incoming c onnec tion arrives, you c an acc ept it with the ac cept func tion. s The socket that has been plac ed in a listening state with the listen func tion.
Winsock C++ programming tutorial Page 17 / 46

Basic winsock functions - MadWizard.org

addr Optional pointer to a buffer that receives the address of the remote socket. This parameter is a pointer to a soc kaddr structure, but its exac t structure is determined by the address family. addrlen Optional pointer to an integer that c ontains the length of addr. Before c alling the function, the value should be the size of the buffer pointed to by addr. On return, the value is the size of the data returned in the buffer. As you know, when a connec tion is ac cepted a new socket is c reated on the server side. This new soc ket is c onnected to the c lient soc ket, all operations on that connec tion are done with that soc ket. The original listening socket is not c onnected, but instead listens for more inc oming connec tions.
sockaddr_in int SOCKET remoteAddr; iRemoteAddrLen; hRemoteSocket;

iRemoteAddrLen = sizeof(remoteAddr); hRemoteSocket = accept(hSocket, (sockaddr*)&remoteAddr, &iRemoteAddrLen); if (hRemoteSocket==INVALID_SOCKET) { // error handling code }

If ac c ept succ eeds, a c onnection is established and the return value is a new socket handle that is the server side of the new connection. Optionally, you can set the addr and addrlen parameters that will receive a sockaddr structure containing the remote address information (IP & port number).
9 . s e nd a nd r ec v

int send(SOCKET s, const char *buf, int len, int flags); s The c onnected soc ket to send data on. buf Pointer to a buffer c ontaining the data to send len Length of the data pointed to by buf. flags Specifies the way in which the call is made. int recv(SOCKET s, char *buf, int len, int flags); s The c onnected soc ket to rec eive data from. buf Pointer to a buffer that will rec eive the data. len Length of the buffer pointed to by buf. flags Specifies the way in which the call is made.
Winsock C++ programming tutorial Page 18 / 46

Basic winsock functions - MadWizard.org

To transfer data on a c onnection, you use the send and recv func tions. Send sends the data in the buffer on the soc ket and returns the number of bytes sent. Rec v rec eives the data that is c urrently available at the socket and stores it in the buffer. The flags parameter can usually be set to zero for both recv and send. In blocking mode, send will bloc k until all data has been sent (or an error oc curred) and rec v will return as much information as is c urrently available, up to the size of the buffer spec ified. Although these func tions may seem simple at first, they become more c omplic ated in non- blocking mode. When a soc ket is in non-blocking mode, these functions c annot block until the operation is finished so they may not perform the operation fully (ie. not all data is sent), or not at all. The next c hapter will explain these issues in great detail, I won't discuss it here sinc e this only a function overview. This example of rec v and send on a c onnected soc ket in blocking mode will just send bac k all data it rec eives.
char buffer[128]; while(true) { // Receive data int bytesReceived = recv(hRemoteSocket, buffer, sizeof(buffer), 0); if (bytesReceived==0) // connection closed { break; } else if (bytesReceived==SOCKET_ERROR) { // error handling code } // Send received data back if (send(hRemoteSocket, buffer, bytesReceived, 0)==SOCKET_ERROR) { // error handling code } }

1 0 . Us a ge

As stated in this c hapter's introduction, this was only an overview of the main winsock func tions. Just knowing how the functions is not enough to program c orrec tly with winsock. The next c hapters will tell you how to use them correctly, whic h I/O strategies exist and how bloc king and non-blocking mode works.

I/O models
In c hapter 3 I briefly touc hed blocking and non-blocking sockets, which play a role in the available winsock I/O models. An I/O model is the method you use to c ontrol the program flow of the c ode that deals with the network input and output. Winsock provides several functions to design an I/O strategy, I will disc uss them all here in short to get an overview. Later in the tutorial I will deal with most models separately and show some examples of them.

1. T he ne e d for an I/O mode l
So why do you need an I/O model? We don't have infinite network speed, so when you send or
Winsock C++ programming tutorial Page 19 / 46

I/O models - MadWizard.org

rec eive data the operation you asked for may not be c ompleted immediately. Espec ially with networks, which are slow c ompared to 'normal', loc al operations. How do you handle this? You c ould c hoose to do other things while you're waiting to try again, or let your program wait until the operation is done, etc. The best c hoice depends on the structure and requirements of your program. Originally, Berkeley soc kets used the blocking I/O model. This means that all socket func tions operate synchronously, ie. they will not return before the operation is finished. This kind of behavior is often undesirable in the Windows environment, bec ause often user input and output should still be processed even while network operations might occ ur (I explained this earlier in c hapter 3). To solve this problem, non-blocking soc kets were introduced.

2. Non-blocking model
A socket can be set into non-blocking mode using ioctlsocket (with FIONBIO as its c md parameter). Some functions used in I/O models implicitly set the socket in non-blocking mode (more on this later). When a socket is in non-blocking mode, winsoc k functions that operate on it will never block but always return immediately, possibly failing because there simply wasn't any time to perform the operation. Non-blocking soc kets introduce a new winsock error c ode whic h - unlike other errors - is not exc eptional. For now, keep the following in mind:
WSAEWOULDBLOCK This constant is the error code a winsock function sets when it cannot immediately perform an operation on a non-blocking socket. You get this error code when you call WSAGetLastError after a winsock function failed. Its name literally says 'error, would block', meaning that the function would have to block to complete. Since a non-blocking socket should not block, the function can never do what you ask it to. Note that this isn't really an error. It can occur all the time when using nonblocking sockets. It just says: I can't do that right now, try again later. The I/O model usually provides a way to determine what's the best time to try again.

3. I/O mode ls
I've made several attempts to find a c ategoric al description of the several I/O models but I haven't really found a good one, mainly bec ause the models' properties overlap and terms like (a)sync hronous have slightly different meanings or apply to different things for each model. So I dec ided to just create a table with all the models to show the differences and explain the details later.
Notification method Model Blocking sockets Polling Select WSAAsyncSelect WSAEventSelect Overlapped I/O: blocking Overlapped I/O: polling Overlapped I/O: completion routines Overlapped I/O: completion ports Blocking mode blocking non-blocking both non-blocking non-blocking N/A N/A N/A N/A x callback function completion port x x blocking select window message event objects blocking call none on network event on completion

Winsock C++ programming tutorial

Page 20 / 46

I/O models - MadWizard.org

The first five models are c ommonly used and fairly easy to use. The last four ac tually use the same model (overlapped I/O), but use different implementation methods. Actually, you don't really need overlapped I/O unless you're writing network programs that should be able to handle thousands of c onnections. Most people won't write such programs but I included them because good information and tutorials about the overlapped I/O model is not easy to find on the web. If you're not interested in overlapped I/O you c an safely skip the future c hapters about them. One way to divide the I/O models is based on the bloc king mode it uses. The blocking sockets model naturally uses bloc king mode, while the others use non-blocking mode (select may be used for both). The bloc king mode is not applic able to overlapped I/O bec ause these operations always operate async hronously (the blocking mode c annot affec t this nor the other way around). Another way to divide them is using their differences in the notific ation method used (if any). There are three subtypes: None There is no notification of anything, an operation simply fails or suc c eeds (optionally blocking). On network event A notification is sent on a specific network event (data available, ready to send, inc oming connec tion waiting to be acc epted, etc.). Operations fail if they c annot c omplete immediately, the network event notific ation c an be used to determine the best time to try again. On completion A notification is sent when a pending network operation has been c ompleted. Operations either succ eed immediately, or fail with an 'I/O pending' error c ode (assuming nothing else went wrong). You will be notified when the operation does complete, eliminating the need to try the operation again. Blocking mode doesn't use any notific ations, the call will just block until the operation finished. WSAAsync Select is an example of a network event notific ation model as you will be notified by a window message when a spec ific network event occ urred. The c ompletion notific ation method is solely used by overlapped I/O, and is far more effic ient. They are bound directly to the operations; the big differenc e between the network event and c ompletion notific ation is that a completion notific ation will be about a spec ific operation you requested, while a network event c an happen bec ause of any reason. Also, overlapped I/O operations c an - like its name says - overlap. That means multiple I/O requests c an be queued. In the next section I will show you the details of eac h model separately. To give you a more intuitive view of the models, I've created timeline images and used a c onversation between the program and winsoc k as an analogy to how the model works. Note In many of these timelines I've assumed the winsock operation fails (in a WSAEWOULDBLOCK way) bec ause that is the interesting case. The func tion might as well suc ceed and return immediately if the operation has been done already. I've left this c ase out in most of the timelines in favor of c larity.

Winsock C++ programming tutorial

Page 21 / 46

I/O models - MadWizard.org

4. Blocking socke ts
Blocking soc kets are the easiest to use, they were already used in the first socket

implementations. When an operation performed on a blocking socket c annot c omplete immediately, the socket will block (ie. halt exec ution) until it is completed. This implies that when you call a winsock function like send or rec v, it might take quite a while (c ompared to other API c alls) before it returns. This is the timeline for a bloc king soc ket:

As you can see, as soon as the main thread c alls a winsock func tion that couldn't be completed immediately, the function will not return until it is c ompleted. Naturally this keeps the program flow simple, since the operations c an be sequenc ed easily. By default, a socket is in blocking mode and behaves as shown above. As I told earlier, I will also show eac h I/O model in the form of a conversation between the program and winsock. For blocking soc kets, it's very simple: program: send this data winsock: okay, but it might take some time ... ... ... done!

5. Polling
Polling is actually a very bad I/O model in windows, but for completeness' sake of I will describe it. Polling is an I/O model for non-blocking sockets, so the socket first has to be put into non-blocking mode. This c an be done with ioctlsocket . Polling in general is repeating something until its status is the desired one, in this case repeating a winsock function until it returns successfully:

Winsock C++ programming tutorial

Page 22 / 46

7/23/2010

I/O models - MadWizard.org

Bec ause the soc ket is non- bloc king, the function will not block until the operation is finished. If it c annot perform the operation it has to fail (with WSAEWOULDBLOCK as error code). The polling I/O model just keeps c alling the function in a loop until it suc ceeds: program: send this data winsock: sorry can't do that right now, I would block program: send this data winsock: sorry can't do that right now, I would block program: send this data winsock: sorry can't do that right now, I would block program: send this data winsock: sorry can't do that right now, I would block program: send this data winsock: done! As I said, this is a really bad method bec ause its effec t is the same as a blocking function, exc ept that you have some control inside the loop so you c ould stop waiting when some variable is set, for example. This style of sync hronization is c alled 'busy waiting', whic h means the program is c ontinuously busy with waiting, wasting precious CPU time. Bloc king soc kets are far more effic ient since they use an efficient wait state that requires nearly no CPU time until the operation c ompletes. Now you know how the polling I/O model works, forget about it immediately and avoid it by all means :)

6. Se le ct
Selec t provides you a more c ontrolled way of bloc king. Although it c an be used on blocking sockets too, I will only foc us on the non- bloc king socket usage. This is the timeline for selec t:

V

Winsock C++ programming tutorial

Page 23 / 46

I/O models - MadWizard.org

And the c orresponding c onversation: program: send this data winsock: sorry can't do that right now, I would block program: okay, tell me when's the best time to try again (the select call) winsock: sure, hang on a minute ... ... try again now! program: send this data winsock: done! You might have notic ed that the selec t call looks suspic iously similar to the blocking soc ket timeline. This is bec ause the select function does block. The first c all tries to perform the winsock operation. In this case, the operation would block but the func tion can't so it returns. Then at one point, selec t is c alled. Select will wait until the best time to retry the winsock operation. So instead of bloc king winsoc k functions, we now have only one func tion that bloc ks, selec t. If selec t blocks, why use it for non- bloc king soc kets then? Selec t is more powerful than blocking soc kets bec ause it c an wait on multiple events. This is the prototype of selec t: select PROTO nfds:DWORD, readfds:DWORD, writefds:DWORD, exceptfds:DWORD,

timeout:DWORD Selec t determines the status of one or more sockets, performing synchronous I/O if necessary. The nfds parameter is ignored, selec t is one of the original Berkeley sockets functions, it is provided for c ompatibility. The timeout parameter c an be used to spec ify an optional timeout for the func tion. The other three parameters all specify a set of soc kets. readfds is a set of sockets that will be c hec ked for readability writefds is a set of sockets that will be c hecked for writability exceptfds is a set of sockets that will be c hecked for errors Readability means that data has arrived on a soc ket and that a call to read after select is likely to rec eive data. Writability means it's a good time to send data sinc e the rec eiver is probably ready to rec eive it. Exceptfds is used to c atc h errors from a non- bloc king c onnect c all as well as out- ofband data (whic h is not disc ussed in this tutorial). So while selec t may bloc k you have more control over it sinc e you c an spec ify more than one soc ket to wait on for a spec ific event, and multiple types of events (data waiting, ready to send or some error that has occ urred). Selec t will be explained more detailed in later c hapters.

7. Windows message s (WSAASyncSe le ct)
Many windows programs have some kind of window to get input from and give information to the user. Winsock provides a way to integrate the network event notific ation with a windows's message handling. The WSAAsyncSelect function will register notific ation for the spec ified network events in the form of a custom window message.
Winsock C++ programming tutorial Page 24 / 46

I/O models - MadWizard.org

WSAAsyncSelect PROTO s:DWORD, hWnd:DWORD, wMsg:DWORD, lEvent:DWORD This function requires a c ustom message (wMsg) that the user chooses and the window procedure should handle. lEvent is a bit mask that selects the events to be notified about. The timeline is as follows:

Let's say the first message wants to write some data to the socket using send. Bec ause the soc ket is non-blocking, send will return immediately. The call might succ eed immediately, but here it didn't (it would need to block). Assuming WSAAsyncSelect was setup to notify you about the FD_WRITE event, you will eventually get a message from winsock telling you a network event has happened. In this case it's the FD_WRITE event which means something like: "I'm ready again, try resending your data now". So in the handler of that message, the program tries to send the data again, and this is likely to succ eed. The conversation between the program and winsock is muc h like the one with selec t, the difference is in the method of notific ation: a window message instead of a sync hronous select c all. While selec t blocks waiting until an event happens, a program using WSAASync Selec t can c ontinue to process windows messages as long as no events happen. program registers for network event notification via window messages program: winsock: send this data sorry can't do that right now, I would block

program handles some message program handles some other message program gets a notification window message from winsock program: winsock: send this data done!

WSAAsync Select provide a more 'Windows natural' way of event notific ation and is fairly easy to use. For low traffic servers (ie. < 1000 connections) it effic ient enough as well. The drawback is that window messages aren't really fast and that you'll need a window in order to use it.

Winsock C++ programming tutorial

Page 25 / 46

I/O models - MadWizard.org

8. Ev e nt obje cts (WSAEv e ntSe le ct)
WSAAsync Select brother is WSAEventSelec t, whic h works in a very similar way but uses event objec ts instead of windows messages. This has some advantages, including a better separation of the network c ode and normal program flow and better efficiency (event objects work faster than window messages). Have a good look at the timeline and conversation, it looks a bit c omplic ated but it really isn't:

program registers for network event notification via event objects program: winsock: program: winsock: send this data sorry can't do that right now, I would block send this data done!

program waits for the event object to signal

It's hard to draw a timeline for this function since event objects are a very powerful mechanism that c an be used in many ways. I c hose for a simple example here as this I/O model will be explained in great detail later in this tutorial. At first, this model seems a lot like blocking: you wait for an event object to be signaled. This is true, but you can also wait for multiple events at the same time and create your own event objec ts. Event objec ts are part of the windows API, winsoc k uses the same objects. Winsock does have special functions to c reate the event objec ts but they are just wrappers around the usual functions. All that winsock does with this model is signaling an event objec t when a winsock event happens. How you use this notific ation method is up to you. That makes it a very flexible model. The function used to register for network events is WSAEventSelect. It is much like

WSAAsync Select: WSAEventSelect PROTO s:DWORD, hEventObject:DWORD, lNetworkEvents:DWORD

Winsock C++ programming tutorial

Page 26 / 46

I/O models - MadWizard.org

WSAAsync Select will send you a c ustom message with the network event that happened (FD_READ, FD_WRITE, etc.). Unlike WSAAsync Selec t, WSAEventSelect has only one way of notific ation: signaling the event objec t. When the objec t is signaled, one or more events may have happened. Which events exac tly c an be found out with WSAEnumNetworkEvents.

9. Use with thre ads
Before starting with the overlapped I/O models I first want to explain some things about the use of threads. Some of the models explained c an show different behavior when threads come into play. For example, blocking sockets in a single threaded applic ation will block the whole application. But when the blocking sockets are used in a separate thread, the main thread c ontinues to run while the helper thread bloc ks. For low traffic servers (let's say 10 connec tions or so), an easy to implement method is to use the select model with one thread per c lient. Each running thread is bound to a spec ific connec tion, handling requests and responses for that partic ular c onnection. Other ways of using threads are possible too, like handling multiple c onnections per thread to limit the number of threads (this is useful for servers with many c onnections), or just one main thread to handle the user input/GUI and one worker thread that deals with all the socket I/O. The same thing holds for the other models, although some combine better with threads than others. For example, WSAAsyncSelect uses window messages. You c ould use threads but you somehow have to pass the received messages to the worker threads. Easier to use is WSAEventSelec t, sinc e threads c an wait on events (even multiple) so notific ations c an be directly acted on in the thread. Pure blocking sockets c an be used as well, but it's hard to get some c ontrol over a thread that is blocked on a winsock func tion (selec t has the same problem). With events, you c an c reate a c ustom event (not winsock related) and use that to notify the thread about something that hasn't got to do with soc ket I/O like shutting down the server. As you can see, threads c an be very powerful and c hange the abilities of an I/O model radic ally. Many servers need to handle multiple requests at the same time so that's why threads are a logical c hoic e to implement this; threads all run at the same time. In later c hapters I will disc uss the use of threads, for now it's enough to know you c an use them.

10. Introduction to Ov e rlappe d I/O
Overlapped I/O is very effic ient and when implemented well also very sc alable (allowing many, many c onnections to be handled). This is especially true for overlapped I/O in c ombination with c ompletion ports. I said before that for most uses overlapped I/O is a bit overkill but I will explain them anyway. The async hronous models disc ussed so far all send some kind of notific ation on the oc currence of a network event like 'data available' or 'ready to send again'. The overlapped I/O models also notify you, but about completion instead of a network event. When requesting a winsock operation, it might either complete immediately or fail with WSA_IO_PENDING as the winsock error c ode. In the latter c ase, you will be notified when the operation is finished. This means you don't have to try again like with the other models, you just wait until you're told it's done. The price to pay for this efficient model is that overlapped I/O is a bit tric ky to implement. Usually one of the other models can stand up to the task as well, prefer those if you don't need really high performance and sc alability. Also, the windows 9x/ME series do not fully support all overlapped I/O
Winsock C++ programming tutorial Page 27 / 46

I/O models - MadWizard.org performance and sc alability. Also, the windows 9x/ME series do not fully support all overlapped I/O

models. While NT4/2K/XP has full kernel support for overlapped I/O, win9x/ME has none. However for some devic es (including sockets), overlapped I/O is emulated by the windows API in win9x/ME. This means you c an use overlapped I/O with winsock for win9x/ME, but NT+ has a much greater support for it and provides more func tionality. For example, I/O c ompletion ports are not available at all on win9x systems. Besides, if you're writing high- performanc e applications that require overlapped I/O I strongly rec ommend running it on an NT+ system. As with the network event notific ation models, overlapped I/O c an be implemented in different ways too. They differ in the method of notific ation: blocking, polling, c ompletion routines and c ompletion ports.

11. Ov e rlappe d I/O: blocking on e v e nt
The first overlapped I/O model I'm going to explain is using an event objec t to signal c ompletion. This is much like WSAEventSelec t, exc ept that the objec t is set into the signaled state on c ompletion of an operation, not on some network event. Here's the timeline:

As with WSAEventSelec t, there are many ways to use the event objec t. You c ould just wait for it, you c ould wait for multiple objec ts, etc . In the timeline above a blocking wait is used, matc hing this simple conversation: program: winsock: program waits operation send this data okay, but I couldn't send it right now for the event object to signal, indicating completion of the

As you can see, the winsock operation is actually performed at the same time as the main thread is running (or waiting in this case). When the event is signaled, the operation is c omplete and the main thread c an perform the next I/O operation. With network event notific ation models, you probably had to retry the operation. This is not nec essary here.

Winsock C++ programming tutorial

Page 28 / 46

I/O models - MadWizard.org

12. Ov e rlappe d I/O: polling
Just like the polling model mentioned earlier, the status of an overlapped I/O operation c an be polled too. The WSAGetOverlappedResult func tion c an be used to determine the status of a pending operation. The timeline and c onversation are pretty muc h the same as the other polling model, exc ept for that the operation happens at the same time as the polling, and that the status is the completion of the operation, not whether the operation suc c eeded immediately or would have blocked.

program: send this data winsock: okay, but I couldn't send it right now program: are you done yet? winsock: no program: are you done yet? winsock: no program: are you done yet? winsock: no program: are you done yet? winsock: no program: are you done yet? winsock: yes! Again, polling isn't very good as it puts too much stress on the CPU. Continuously asking if an operation c ompletes is less effic ient than just waiting for it in an effic ient, little CPU c onsuming wait state. So I don't c onsider this a very good I/O model either. This doesn't render WSAGetOverlappedResult useless though, it has more uses, whic h I will show when the tutorial c omes to the c hapters about overlapped I/O.

13. Ov e rlappe d I/O: comple tion routine s
Completion routines are c allback routines that get c alled when an operation (which you associated with the routine) c ompletes. This looks quite simple but there is a tricky part: the c allbac k routine is c alled in the context of the thread that initiated the operation. What does that mean? Imagine a thread just asked for an overlapped write operation. Winsock will perform this operation while your
Winsock C++ programming tutorial Page 29 / 46

I/O models - MadWizard.org

main thread continues to run. So winsock has its own thread for the operation. When the operation finishes, winsock will have to call the c allbac k routine. If it would just c all it, the routine would be run in the context of the winsock thread. This means the c alling thread (the thread that asked for the operation) would be running at the same time as the c allback routine. The problem with that is that you don't have synchronization with the calling thread, it doesn't know the operation c ompleted unless the c allbac k tells him somehow. To prevent this from happening, winsock makes sure the callbac k is run in the c ontext of the c alling thread by using the APC (Async hronous Procedure Call) mec hanism included in windows. You c an look at this as 'injecting' a routine into a threads program flow so it will run the routine and then continue with what it was doing. Of c ourse the system can't just say to a thread: "Stop doing whatever you were doing, and run this routine first!". A thread can't just be intervened at any point. In order to deal with this, the APC mec hanism requires the thread to be in a so-c alled alertable wait state. Each thread has its own APC queue where APCs are waiting to be c alled. When the thread enters an alertable wait state it indic ates that it's willing to run an APC. The function that put the thread in this wait state (for example SleepEx, WaitForMultipleObjec tsEx and more) either returns on the normal events for that function (timeout, triggered event etc.) or when an APC was executed. Overlapped I/O with c ompletion routines use the APC mec hanism (though slightly wrapped) to notify you about c ompletion of an operation. The timeline and c onversation are:

program: winsock:

send this data okay, but I couldn't send it right now

program enters an alertable wait state the operation completes winsock: the wait program system, queue this completion routine for that thread function executes the queued completion
Page 30 / 46

the wait state the program is in is alerted routine and returns to the

Winsock C++ programming tutorial

I/O models - MadWizard.org

APCs can be a bit hard to understand but don't worry, this is just an introduction. Usually a thread is in the alertable wait state until the c allbac k is c alled, whic h handles the event and returns to the thread. The thread then does some operations if necessary and finally loops bac k to the wait state again.

14. Ov e rlappe d I/O: comple tion ports
We've finally c ome to the last and probably most efficient winsoc k I/O model: overlapped I/O with c ompletion ports. A completion port is a mechanism available in NT kernels (win9x/ME has no support for it) to allow efficient management of threads. Unlike the other models discussed so far, c ompletion ports have their own thread management. I didn't draw a timeline nor made a c onversation for this model, as it probably wouldn't make things c learer. I did draw an image of the mec hanism itself, have a good look at it first:

The idea behind completion ports is the following. After c reating the completion port, multiple soc kets (or files) can be associated with it. At that point, when an overlapped I/O operation c ompletes, a completion pac ket is sent to the completion port. The c ompletion port has a pool of similar worker threads, eac h of which are blocking on the completion port. On arrival of a c ompletion packet, the port takes one of the inactive queued threads and ac tivates it. The activated thread handles the completion event and then blocks again on the port. The management of threads is done by the c ompletion port. There are a certain number of threads running (waiting on the completion port actually), but usually not all of them are ac tive at the same time. When c reating the c ompletion port you c an spec ify how many threads are ac tive at the same time. This value defaults to the number of CPUs in the system. Completion ports are a bit c ounter intuitive. There is no relation between a thread and a c onnection or operation. Each thread has to be able to ac t on any c ompletion event that happened on the completion port. I/O completion ports (IOCP) are not easy to implement but provide a very good scalability. You will be able to handle thousands of c onnections with IOCP.

15. Conclusion
I hope you now have a global view of all the I/O models available. Don't worry if you don't fully understand them, the next chapters will explain them more detailed, one at a time.

Winsock C++ programming tutorial

Page 31 / 46

Blocking sockets: client - MadWizard.org

Blocking sockets: client
The first I/O model I'm going to explain to you is the simplest one, the bloc king soc kets. Winsoc k func tions operating on blocking sockets will not return until the requested operation has c ompleted or an error has oc curred. This behavior allows a pretty linear program flow so it's easy to use them. In c hapter 4, you've seen the basic winsock func tions. These are pretty much all func tions you need to program blocking soc kets, although I will show you some additional func tions that may be useful in this c hapter. You might not be very interested in blocking sockets if you plan to use an I/O model that uses nonblocking socket. Nonetheless, I strongly rec ommend you to read the c hapters about bloc king sockets too sinc e they cover the socket programming basics and other useful winsoc k features I will assume you remember for the next chapters.
1. A s im ple c lient

The first example is a simple c lient program that connec ts to a website and makes a request. It will be a console application as they work well with blocking sockets. I won't assume you have deep knowledge of the HTTP (the protocol used for the web), this is what happens in short: The c lient c onnects to the server (on port 80 by default) The server acc epts the c onnection and just waits The c lients sends its HTTP request as an HTTP request message The server responds to the HTTP request with an HTTP response message The server c loses the c onnection* *) This depends on the value of the connection HTTP header, but to keep things simple, we assume the c onnection will always be c losed. HTTP follows the typic al c lient- server model, the client and server talk to eac h other in turns. The c lient initiates the requests; the server reac ts with a response. An HTTP request includes a request method of whic h the three most used are GET and POST and HEAD. GET is used to get a resource from the web (webpage, image, etc.). POST sends data to the server first (like form data filled by the user), then rec eives the server's response. Finally, HEAD is the same as GET, except for that the actual data is not send by the server, only the HTTP response message. HEAD is used as a fast way to see if a page has been modified without having to download the full page data. In the example program I will use HEAD sinc e GET can return quite some data while HEAD will only return a response c ode and set of headers so the program's output easier to read. A typic al HTTP request with the HEAD request method looks like this: HEAD / HTTP/1.1 <crlf> Host: www.google.com <crlf> User-agent: HeadReqSample <crlf> Connection: close <crlf>
<crlf>

The first / in the fist line is the requested page, in this c ase the server's root (default page).
Winsock C++ programming tutorial Page 32 / 46

Blocking sockets: client - MadWizard.org

HTTP/1.1 indicates version 1.1 of the HTTP protocol is used. After this first spec ial line that contains the c ommand follows a set of header in the form "header-name: value", terminated by a blank line. As line terminators, a combination of carriage return (CR, 0x0D) and line feed (LF, 0x0A) is used. That last blank line indic ates the end of the c lient's request. As soon as the server detec ts this, it will send bac k a response in this form: HTTP/1.1 Response-code Response-message <crlf> header-name: value <crlf> header-name: value <crlf> header-name: value <crlf>
<crlf>

As you c an see the response format is much like that of a request. Response- code is a 3-digit c ode that indicates the suc c ess or failure of the request. Typical response codes are 200 (everything OK), 404 (page not found, you probably knew this one :) and 302 (found but located elsewhere, redirect). Response-message is a human- readable version of the response c ode and c an be anything the server likes. The set of headers inc lude information about the requested resource. A HEAD request will result in the above response. If the request method would have been GET, the ac tual page data will be sent bac k by the server after this response message. So far for the crash c ourse HTTP, it's not really nec essary to understand it all to read the examples about bloc king sockets, but now you have some background information too. If you want to read more about HTTP, find the RFC for it (www.rfc -editor.org) or google for HTTP. Another great introduction to HTTP is HTTP made really easy.
2. Pr ogr a m e x am ple

A possible output of the example program c alled HeadReq is shown here: X:\>headreq www.microsoft.com Initializing winsock... initialized. Looking up hostname www.microsoft.com... found. Creating socket... created. Attempting to connect to 207.46.134.190:80... connected. Sending request... request sent. Dumping received data... HTTP/1.1 200 OK Connection: close Date: Mon, 17 Mar 2003 20:14:03 GMT Server: Microsoft-IIS/6.0 P3P: CP='ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo C NT COM INT NAV ONL PHY PRE PUR UNI' Content-Length: 31102 Content-Type: text/html Expires: Mon, 17 Mar 2003 20:14:03 GMT Cache-control: private
Winsock C++ programming tutorial Page 33 / 46

Blocking sockets: client - MadWizard.org

Cleaning up winsock... done. If the program's parameter (www.mic rosoft.c om) is omitted, www.google.c om is used.
3. Hostnam e s

So what do we need for the c lient? I'm assuming you have the address of the webpage (www.google.com for example) and you want to get the default webpage for it, like the page you get when entering www.google.com in your web browser (in order to keep things simple we will only receive the server's response headers, not the actual page). As you know from c hapter 4, you c an c onnec t a socket to a server with the connect function, but this function requires a sockaddr structure (or sockaddr_in in the case of TCP/IP). How do we build up this structure? Sockaddr_in needs an address family, an IP number and a port number. The address family is simply AF_INET. The port number is also easy; the default for the HTTP protocol is port 80. What about the IP, we only got a hostname? If you remember c hapter 2 there's a DNS server that knows whic h IPs c orrespond to which hostnames. To find this out, winsoc k has a func tion c alled gethostbyname: hostent * gethostbyname(const char *name); You simply provide this func tion a hostname as a string (eg. "www.google.com") and it will return a pointer to a hostent structure. This hostent struc ture contains a list of addresses (IPs) that are valid for the given hostname. One of these IPs can then be put into the sockaddr_in structure and we're done.
4. Fr a m e w or k

The program we're going to write will c onnect to a web server, send a HEAD HTTP request and dump all output. An optional parameter spec ifies the server name to c onnec t to, if no name is given it defaults to www.google.c om. First of all, we define the framework for the applic ation:
#include <iostream> #define WIN32_MEAN_AND_LEAN #include <winsock2.h> #include <windows.h> using namespace std; class HRException { public: HRException() : m_pMessage("") {} virtual ~HRException() {} HRException(const char *pMessage) : m_pMessage(pMessage) {} const char * what() { return m_pMessage; } private: const char *m_pMessage; }; int main(int argc, char* argv[]) { // main program }

Winsock C++ programming tutorial

Page 34 / 46

Blocking sockets: client - MadWizard.org

The winsock headers are already included by windows.h, but bec ause we use some winsock 2 spec ific things we also need to include winsock2.h. Include this file before windows.h to prevent it from inc luding an older winsock version first. We will also need the STL's iostream c lasses, so we included those too. Don't forget to link to ws2_32.lib, or you'll get a bunc h of unresolved symbol errors. The HRExc eption class is a simple exception c lass used to throw errors that occ ur. One of its c onstructors takes a const char * with an error message that c an be retrieved with the what() method.
5. Cons tants and globa l da ta

The program will need some c onstants and global data, whic h we define in the following code snippet:
const const const const int char int int REQ_WINSOCK_VER DEF_SERVER_NAME[] SERVER_PORT TEMP_BUFFER_SIZE = = = = 2; // Minimum winsock version required "www.google.com"; 80; 128;

const char HEAD_REQUEST_PART1[] = { "HEAD / HTTP/1.1\r\n" // Get root index from server "Host: " // Specify host name used }; const char HEAD_REQUEST_PART2[] = { "\r\n" "User-agent: HeadReqSample\r\n" "Connection: close\r\n" "\r\n" }; // IP number typedef for IPv4 typedef unsigned long IPNumber;

// // // //

End hostname header from part1 Specify user agent Close connection after response Empty line indicating end of request

These c onstants and data define the default hostname (www.google.c om), server port (80 for HTTP), receive buffer size, and the minimum (major) winsock version required (2 or higher in our c ase). Furthermore, the full HTTP request is put in two variables. The request is split up because the hostname of the server needs to be inserted as the host header (see the HTTP message examples above). While all strings in C automatic ally get a 0 byte at the end to terminate it, we don't actually treat it as a null-terminated string. Only the text itself will be send, without the null terminator. Finally, unsigned long is typedef'ed to IPNumber to make the c ode a bit c learer.
6. The m a in func tion

The first thing to do is initializing winsock. We will do this in the main function and write the ac tual c ode for the HTTP request in a different func tion named RequestHeaders. The main function is:
int main(int argc, char* argv[]) { int iRet = 1; WSADATA wsaData; cout << "Initializing winsock... "; if (WSAStartup(MAKEWORD(REQ_WINSOCK_VER,0), &wsaData)==0) { // Check if major version is at least REQ_WINSOCK_VER if (LOBYTE(wsaData.wVersion) >= REQ_WINSOCK_VER) { cout << "initialized.\n";

Winsock C++ programming tutorial

Page 35 / 46

Blocking sockets: client - MadWizard.org
// Set default hostname: const char *pHostname = DEF_SERVER_NAME; // Set custom hostname if given on the commandline: if (argc > 1) pHostname = argv[1]; } else { } cout << "Cleaning up winsock... "; // Cleanup winsock if (WSACleanup()!=0) { cerr << "cleanup failed!\n"; iRet = 1; } cout << "done.\n"; } else { cerr << "startup failed!\n"; } return iRet; } iRet = !RequestHeaders(pHostname);

cerr << "required version not supported!";

The value the main function returns will be given back as exit code to the OS. Sinc e the c onvention for c ommand line program is that an exit code of 0 indicates succ ess while other values indicate some kind of error, we will follow this and return the correc t value depending on the suc c ess of the winsock initialization and the RequestHeaders function. First of all, WSAStartup is c alled. It wants the highest winsoc k version your program supports (REQ_WINSOCK_VER) and fills in a WSADATA struc ture. After we check if this func tion suc ceeded, we still need to check which winsoc k version has been loaded, since this might be less than REQ_WINSOCK_VER (see c hapter 4). If the major version number is at least REQ_WINSOCK_VER, we got the right version. Then, argc is checked to see if a parameter was given to the program. If there was, it should be a hostname and instead of the default hostname, the parameter comes from argv and is passed on to RequestHeaders. If WSAStartup succ eeded, a matc hing call to WSACleanup is needed. This is done at the end of the c ode.
7. Re que stHe ade rs

RequestHeaders is the function where all the magic happens. The basic structure of it is:
bool RequestHeaders(const char *pServername) { SOCKET hSocket = INVALID_SOCKET; char tempBuffer[TEMP_BUFFER_SIZE]; sockaddr_in sockAddr = {0}; bool bSuccess = true; try { // code goes here } catch(HRException e) { cerr << "\nError: " << e.what() << endl; bSuccess = false; }

Winsock C++ programming tutorial

Page 36 / 46

Blocking sockets: client - MadWizard.org
return bSuccess;

}

As a parameter, RequestHeaders gets the name of the server to connec t to. There are some variables we will use, the socket handle, a temporary buffer used to store rec eived data and a sockaddr_in struc ture for the server's address. The soc ket handle is initialized to INVALID_SOCKET, the only value that c an't be used as a soc ket handle. bSucc ess is a bool that is set to false if the func tion fails. The main c ode is surrounded by a try-c atch bloc k, any error that occ urs is thrown as a standard STL exc eption and c aught by this func tion. The cleanup c ode will be after the try-c atch block, so cleaning up happens both when everything succ eeds and on failure. The RequestHeaders function has the following tasks: Resolve the hostname to its IP. Create a soc ket. Connect the socket to the remote host. Send the HTTP request data. Rec eive data and print it until the other side c loses the connection. Cleanup I will show you how to implement eac h step in the next sec tions.
8. Re solving the hos tna m e to its IP

To connec t to the server, we need to fill a sockaddr_in structure with its address. As I said earlier, this structure consists of an address family (always AF_INET), an IP number and a port number. Although the port number is not always 80 for web servers, we will assume it is. I also explained gethostbyname can be used to lookup a hostname at the DNS server and retrieve its IP number. The next function of our program,FindHostIP, uses this winsock function. Note that looking up a host involves a request to a DNS server so it might take some time (typically only 10 milliseconds or so but that's slow c ompared to normal c ode). If the hostname isn't found, it might even take sec onds. Bec ause we are using blocking sockets, the program will simply hang on gethostbyname until it either succ eeds or fails. While gethostbyname is running, we have no control over our program. But as the program is a c onsole program, this doesn't matter.
IPNumber FindHostIP(const char *pServerName) { HOSTENT *pHostent; // Get hostent structure for hostname: if (!(pHostent = gethostbyname(pServerName))) throw HRException("could not resolve hostname."); // Extract primary IP address from hostent structure: if (pHostent->h_addr_list && pHostent->h_addr_list[0]) return *reinterpret_cast<IPNumber*>(pHostent->h_addr_list[0]); return 0; }

Gethostbyname takes a hostname as its single parameter and returns a pointer to a hostent struc ture. Note that it c annot handle hostnames that are IPs in string form (like "101.102.103.104"). Therefore our program does not ac cept an IP number as server name in the first
Winsock C++ programming tutorial Page 37 / 46

Blocking sockets: client - MadWizard.org

parameter. If you would want to allow this, the string c an be c onverted into a number with the inet_addr function. If the func tion fails it returns NULL, whic h is the first thing we c heck. It means the server name c ould not be resolved. If it did succ eed, we now have a hostent struc ture pointer. This allocated memory doesn't need to be freed; winsock has a piece of memory for eac h thread specific ally for storing this data in. However this does imply that on the next c all to gethostbyname, you c annot use the hostent structure returned by a previous c all to it, since it would have been overwritten. The hostent struc ture can c ontain a list of addresses, whic h do not nec essarily have to be IP numbers. Since we use TCP/IP, they will be IP numbers but the structure still has to support other forms of addresses. The h_addr_list member of hostent points to a null- terminated array of other pointers. Each pointer points in that array points to an address. Sinc e the hostent structure does not know the type of addresses used, you need to c ast the pointers to the right type, in this c ase IPNumber*. The FindHostIP c ode extracts the first available IP address from this structure and returns it. Some additional pointer c hec ks ensure that the program doesn't crash if the pointers are not set or arrays are empty. The return value of this function, the IP number in network byte order, is used by FillSockAddr:
void FillSockAddr(sockaddr_in *pSockAddr, const char *pServerName, int portNumber) { // Set family, port and find IP pSockAddr->sin_family = AF_INET; pSockAddr->sin_port = htons(portNumber); pSockAddr->sin_addr.S_un.S_addr = FindHostIP(pServerName); }

All it does is calling FindHostIP and storing the IP in the soc kaddr_in structure pointed to by the pSockAddr parameter. It also c onverts the port number from the portNumber parameter to network byte order and stores it as well. Back to the RequestHeaders func tion we call FillSoc kAddr to fill in our local sockaddr_in structure with the right information:
// Lookup hostname and fill sockaddr_in structure: cout << "Looking up hostname " << pServername << "... "; FillSockAddr(&sockAddr, pServername, SERVER_PORT); cout << "found.\n";

9. Cr e ating a s oc ke t

The next step is to c reate a socket to connec t with. This is quite simple, just call socket with the right parameters:
// Create socket cout << "Creating socket... "; if ((hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) throw HRException("could not create socket."); cout << "created.\n";

If socket fails, it returns INVALID_SOCKET. In that c ase, no further operations are performed and the following cleanup c ode (after the c atc h() handler) is exec uted direc tly:
if (hSocket!=INVALID_SOCKET) closesocket(hSocket);

The c leanup code is always exec uted, whether an error occ urred or not. It first checks if the socket
Winsock C++ programming tutorial Page 38 / 46

Blocking sockets: client - MadWizard.org

handle wasn't INVALID_SOCKET (no socket was c reated). If it isn't, the soc ket handle is valid and needs to be c losed.
10 . Connec ting the soc ke t

Now that we have the socket, we c an connec t it to a remote host with connect. Connec t uses the sockaddr_in struc ture we've setup earlier with FillSoc kAddr and attempts to c onnect the given socket with the addressed host. Here too, c onnect will block until a c onnection has been established or something went wrong. The return value of c onnect is zero if the soc ket is c onnected, otherwise it's SOCKET_ERROR. Before ac tually c onnecting, a message is print with the IP and port number of the remote host. The inet_ntoafunc tion is used to c onvert the numeric IP into a string with the IP in dotted format.
// Connect to server cout << "Attempting to connect to " << inet_ntoa(sockAddr.sin_addr) << ":" << SERVER_PORT << "... "; if (connect(hSocket, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr))!=0) throw HRException("could not connect."); cout << "connected.\n";

11 . Sending the r eques t

When the socket is c onnected the HTTP request can be send. It is sent in three parts, to easily insert the hostname inside the request: HEAD / HTTP/1.1 <crlf> Host: www.google.com <crlf> User-agent: HeadReqSample <crlf> Connection: close <crlf> <crlf> The send calls are pretty straightforward, each call takes a buffer and sends the specified amount of bytes from it to the remote host. Send will block until all the data has been sent, or fail and return SOCKET_ERROR.
cout << "Sending request... "; // send request part 1 if (send(hSocket, HEAD_REQUEST_PART1, sizeof(HEAD_REQUEST_PART1)-1, 0)==SOCKET_ERROR) throw HRException("failed to send data."); // send hostname if (send(hSocket, pServername, lstrlen(pServername), 0)==SOCKET_ERROR) throw HRException("failed to send data."); // send request part 2 if (send(hSocket, HEAD_REQUEST_PART2, sizeof(HEAD_REQUEST_PART2)-1, 0)==SOCKET_ERROR) throw HRException("failed to send data."); cout << "request sent.\n";

Note that the buffer sizes specified are one less than sizeof(buffer), because we don't want to send the null-terminator at the end of the string.
12 . Rec e iving the r e s ponse

The final step of the program before c leaning up is to rec eive data and print it until the other side c loses the connection. The HTTP header "Connec tion: close" in our request tells the server that it
Winsock C++ programming tutorial Page 39 / 46

Blocking sockets: client - MadWizard.org

should c lose the connec tion after it has sent its response. Rec eiving data is done with the recv func tion that rec eives the c urrently available data and puts it in a buffer. I kept the example simple by c hoosing to just dump this output instead of actually doing something with it, so all we have to do is keep c alling recv until the c onnection is c losed. Recv too will block if no data is available immediately and return if some has arrived. The return value of recv is either 0, SOCKET_ERROR or the number of bytes read. SOCKET_ERROR of c ourse indicates a soc ket error, 0 indicates closure of the connec tion. So basic ally we will loop until recv returns 0 (c onnection c losed, done) or SOCKET_ERROR (something went wrong). This leads to the following code:
cout << "Dumping received data...\n\n"; // Loop to print all data while(true) { int retval; retval = recv(hSocket, tempBuffer, sizeof(tempBuffer)-1, 0); if (retval==0) { break; // Connection has been closed } else if (retval==SOCKET_ERROR) { throw HRException("socket error while receiving."); } else { // retval is number of bytes read // Terminate buffer with zero and print as string tempBuffer[retval] = 0; cout << tempBuffer; } }

Take a look at the c all to rec v. tempBuffer is the buffer that will rec eive the data. As the size of the buffer, we spec ify its ac tual size minus one. This is bec ause we will put a 0 byte after the last byte received to transform the raw data into a null terminated string we can easily print. Note that in general, it might be perfec tly possible to have a 0 byte in the rec eived data since TCP/IP data is not restricted to text. You'll have to treat it as binary data. However, the HTTP protocol does not allow 0 bytes in a HTTP response message (only text) so this won't happen. Even if it would happen, the string would be printed wrong (the 0 byte would be wrongly seen as the terminator) but it isn't likely to happen unless the HTTP server is bad (or the server is not a HTTP server). What this c omes down to is that this is just a quic k and dirty way to print all the received data that works find for c orrect HTTP HEAD responses. If you would ac tually do something with the data more c are needs to be taken (for example, a 0 byte in the rec eived data may not be seen as a terminator but indicates a bad HTTP server).
13 . Cle aning up

Finally, the socket is c losed (if it was c reated) as shown earlier and the RequestHeaders func tion will return true or false depending on the suc c ess of the function. Bac k in the main function, winsoc k will be c leaned up (WSACleanup) and the program quits after printing a last message.
14 . Finis hed!

That's all, the program is finished. Download the sourc e zip file here: http://www.madwizard.org/download/winsock/headreq_cpp.zip The zip file c ontains the sourc e files and the binary executable.
Winsock C++ programming tutorial Page 40 / 46

Blocking sockets: server
Now that you've seen how a blocking c lient works, it's time for the blocking server example. This c hapter will explain how to build a simple server that ROT13 enc odes the received data and then sends it bac k. ROT13 (rot stands for rotate) is a very simple encryption method used by Caesar. Each c harac ter in the alphabet is replaced by the charac ter 13 positions farther (the characters rotate 13 places). The encryption is symmetric, that is encryption works exac tly the same as dec rypting. You c an use rot13.com if you want to play with it.

1. Program flow
The program flow is as follows: The server creates a server socket The server socket is bound to an address The server socket is put into the listening state On c onnection attempt, the c onnection is ac c epted and a c lient socket is available The client socket is read, every byte is ROT13'd and sent back. When the client c loses the c onnection, the program ends

2. Framework
The framework is almost the same as that of the blocking c lient example from chapter 6, only the HRException has been renamed to ROTException and some include files were added:
#include <iostream> #include <string> #include <sstream> #define WIN32_MEAN_AND_LEAN #include <winsock2.h> #include <windows.h> using namespace std; class ROTException { public: ROTException() : m_pMessage("") {} virtual ~ROTException() {} ROTException(const char *pMessage) : m_pMessage(pMessage) {} const char * what() { return m_pMessage; } private: const char *m_pMessage; }; int main(int argc, char* argv[]) { // main program }

3. Constants and global data
The program uses a few c onstants for the default server port number (4444), the required winsoc k version and rec eive buffer size.
const int const int const int REQ_WINSOCK_VER DEFAULT_PORT TEMP_BUFFER_SIZE = 2; // Minimum winsock version required = 4444; = 128;

Winsock C++ programming tutorial

Page 41 / 46

Blocking sockets: server - MadWizard.org

4. T he main function
The main function too has a lot of c ommon with the blocking client from the previous c hapter:
int main(int argc, char* argv[]) { int iRet = 1; WSADATA wsaData; cout << "Initializing winsock... "; if (WSAStartup(MAKEWORD(REQ_WINSOCK_VER,0), &wsaData)==0) { // Check if major version is at least REQ_WINSOCK_VER if (LOBYTE(wsaData.wVersion) >= REQ_WINSOCK_VER) { cout << "initialized.\n"; int port = DEFAULT_PORT; if (argc > 1) port = atoi(argv[1]); iRet = !RunServer(port); } else { } cerr << "required version not supported!";

cout << "Cleaning up winsock... "; // Cleanup winsock if (WSACleanup()!=0) { cerr << "cleanup failed!\n"; iRet = 1; } cout << "done.\n";

}

cerr << "startup failed!\n"; } return iRet;

} else {

Winsoc k is initialized, and c leaned up again when the program is finished. In between is the server startup c ode. The program allows an optional parameter that specifies the port the server should run on. If it is not set, the default port number is used (4444). Finally, RunServer is c alled with the final port number as its parameter. The RunServer function c ontains the ac tual server c ode.

5. RunSe rv e r
RunServer is the function where the server is setup and connections are acc epted. The basic framework of this function is:
bool RunServer(int portNumber) { SOCKET hSocket = INVALID_SOCKET, hClientSocket = INVALID_SOCKET; bool bSuccess = true; sockaddr_in sockAddr = {0}; try { // Create socket cout << "Creating socket... "; if ((hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) throw ROTException("could not create socket."); cout << "created.\n"; // code goes here

Winsock C++ programming tutorial

Page 42 / 46

Blocking sockets: server - MadWizard.org
} catch(ROTException e) { cerr << "\nError: " << e.what() << endl; bSuccess = false; } if (hSocket!=INVALID_SOCKET) closesocket(hSocket); if (hClientSocket!=INVALID_SOCKET) closesocket(hClientSocket); return bSuccess; }

A server soc ket is c reated in the usual way, and a variable to hold the client soc ket is reserved too. The c lient soc ket doesn't have to be c reated, since winsoc k will do that for us later. You do have to c lose both socket handles when you won't use them anymore though, this is done in the c leanup part at the end of the c ode.

6. Binding the socke t
After the soc ket is created, we will bind it to an address. As I've explained in the first chapters, a server listens on a specific port number and possibly on a spec ific IP number as well. Before you c an let the server socket listen, it must be bound. The winsock API bind will do that for you. In this example, the socket will be bound to the port spec ified by the portNumber parameter of RunServer, the IP number is set to INADDR_ANY, indic ating that the server will listen on all available IP numbers. To bind a socket with bind, you need to fill in a sockaddr_in struc ture with the address you want the socket be bound to. Setting up this structure is done in a separate function called SetServerSoc kAddr:
void SetServerSockAddr(sockaddr_in *pSockAddr, int portNumber) { // Set family, port and find IP pSockAddr->sin_family = AF_INET; pSockAddr->sin_port = htons(portNumber); pSockAddr->sin_addr.S_un.S_addr = INADDR_ANY; }

This function is c alled in RunServer in the following way:
// Bind socket cout << "Binding socket... "; SetServerSockAddr(&sockAddr, portNumber); if (bind(hSocket, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr))!=0) throw ROTException("could not bind socket."); cout << "bound.\n";

7. Le tting the socke t liste n
If the binding suc c eeds, the socket is put into listening mode. As soon as it's in this state, any c lient c an make a c onnection attempt to the server on the port the soc ket is bound to. Setting the listening mode is simply done by c alling the listen winsock function:
// Put socket in listening mode cout << "Putting socket in listening mode... "; if (listen(hSocket, SOMAXCONN)!=0) throw ROTException("could not put socket in listening mode."); cout << "done.\n";

Listen has two parameters. The first is the socket you want to listen, the second is the length of the queue of pending connec tions. Usually the default value of SOMAXCONN is okay for the latter parameter. This value is the maximum number of c onnections that winsock will hold pending until
Winsock C++ programming tutorial Page 43 / 46

Blocking sockets: server - MadWizard.org

your program ac cepts them. You probably don't need to worry about this value most of the time.

8. Acce pting conne ctions
When the server socket is in the listening state, you need to acc ept the incoming c onnections using the accept function. The ac c ept function bloc ks until a c onnection request c omes in, establishes the connec tion and then returns a c lient socket handle. It is important to know that the server socket's only purpose is now to listen for c onnections and acc ept them. As soon as you acc ept a connection, a new socket is c reated by winsock. This socket is usually c alled the client socket and that's the socket you will be rec eiving and sending data on. This often confuses winsock beginners, some try to rec eive or send data on the listening soc ket, while they should use the c lient socket. Besides ac c epting a c onnection and returning a c lient socket handle, accept also fills in a soc kaddr_in structure with information about the client. Our example will use this information to print a short desc ription of the c lient that connec ted (in the form IP:port).
sockaddr_in clientSockAddr; int clientSockSize = sizeof(clientSockAddr); // Accept connection: hClientSocket = accept(hSocket, reinterpret_cast<sockaddr*>(&clientSockAddr), &clientSockSize); // Check if accept succeeded if (hClientSocket==INVALID_SOCKET) throw ROTException("accept function failed."); cout << "accepted.\n"; // Wait for and accept a connection: HandleConnection(hClientSocket, clientSockAddr);

The above c ode c alls acc ept, and then handles the both the client socket handle and the soc kaddr_in structure to a new function, HandleConnec tion, which will deal with the c onnection. After this c ode has exec uted, RunServer returns and c loses the sockets, as shown earlier.

9. Handle Conne ction
The HandleConnection function handles the c onnection. The first thing it does is showing a short description of the client. A separate func tion (GetHostDesc ription) is used to c reate this description.
void HandleConnection(SOCKET hClientSocket, const sockaddr_in &sockAddr) { // Print description (IP:port) of connected client cout << "Connected with " << GetHostDescription(sockAddr) << ".\n"; char tempBuffer[TEMP_BUFFER_SIZE]; // todo cout << "Connection closed.\n"; }

The GetHostDesc ription func tion looks like this:
string GetHostDescription(const sockaddr_in &sockAddr) { ostringstream stream; stream << inet_ntoa(sockAddr.sin_addr) << ":" << ntohs(sockAddr.sin_port); return stream.str(); }

Winsock C++ programming tutorial

Page 44 / 46

Blocking sockets: server - MadWizard.org

We will now write the part marked as 'todo' in the above HandleConnection framework. The function should loop on recv until the c onnection is closed (rec v returns 0). Every time data is rec eived, it is ROT13 encoded and sent bac k to the c lient. First of all, a simple func tion is written to deal with the ROT13 encryption:
void rot13(char *pBuffer, int size) { for(int i=0;i<size;i++) { char c = pBuffer[i]; if ((c >= 'a' && c < 'n') || (c >= 'A' && c < 'N') ) c += 13; else if ((c>='n' && c <= 'z') || (c>='N' && c <= 'Z')) c -= 13; else continue; pBuffer[i] = c; } }

Then the main loop is simple. First a recv c all, that will receive data from the c lient. The rot13 function is called to enc rypt the rec eived data and finally send is used to send the encrypted data bac k to the c lient:
// Read data while(true) { int retval; retval = recv(hClientSocket, tempBuffer, sizeof(tempBuffer), 0); if (retval==0) { break; // Connection has been closed } else if (retval==SOCKET_ERROR) { throw ROTException("socket error while receiving."); } else { /* retval is the number of bytes received. rot13 the data and send it back to the client */ rot13(tempBuffer, retval); if (send(hClientSocket, tempBuffer, retval, 0)==SOCKET_ERROR) throw ROTException("socket error while sending."); } }

10. T e sting
That's all, it should work now. To test the program, you c ould use the telnet client supplied by windows but you have to get the settings right. If you switc h off the local echo you don't see what you type but you do see what data you receive. This means you see the encrypted text direc tly. However, I prefer a better c lient called PuTTY, you c an find it here. I rec ommend you to download it as well. Compile the program, run it and you will (hopefully) see a message that the program is waiting for a c onnection: X:\asm\rot13server>rot13server Initializing winsock... initialized. Creating socket... created. Binding socket... bound. Putting socket in listening mode... done. Fire up putty, and in the configuration screen, type in localhost as the hostname, 4444 as the port number (or a different one if you choose to run the program with some other port). Set the
Winsock C++ programming tutorial Page 45 / 46

Blocking sockets: server - MadWizard.org

protocol to Raw. Finally press Open to c onnect. You will now see putty's console window. Here you c an type text that will be send to the server. Any data rec eived will be printed in the same window. Note: putty by default has local line editing enabled. This means that you c an type and even edit the text you type as long as you stay on the same line, sinc e it's not send until you press enter. If you use a c lient that immediately sends every c harac ter, you also get a response immediately. If you have suc h a c lient you should disable local ec ho (ie. showing the text you type), otherwise you get your text and the received text interleaved, whic h is pretty hard to read. This is not the c ase with putty. Here's a sc reenshot of the c onnection in action:

11. Source code
Finally, the sourc e c ode: Download the source zip file here: http://www.madwizard.org/download/winsock/rot13server_cpp.zip

12. Conclusion
Now you've seen both a blocking client and a blocking server. Blocking soc kets are relatively easy to use bec ause they fit in nic ely in the program flow. Still, you've only seen pretty simple examples, since both the c lient and the server we showed did prac tic ally nothing with the data other than print it or in this c ase, encrypt and then send it bac k. It gets harder when we have to extrac t meaningful information from the rec eived data like when dealing with a protocol like POP3.
© 2010 by Thomas Bleeker (MadWizard)

Winsock C++ programming tutorial

Page 46 / 46

Sign up to vote on this title
UsefulNot useful