## An Introduction To Network Programming Using Winsock

### Written by Stéphane Richard (MystikShadows)

### INTRODUCTION:

Welcome to this introductory tutorial on network programming using winsock. The subject has been talked about and asked for both on the Official QB Express Article request thread and in a few emails I've received and although there is an example it seems that some of the things could be explained in a bit more details. As such I've decided to create this tutorial that will guide you through using winsock in order to connect to a specific website URL and retrieve information from the server. Since all you can do with winsock is far beyond the scope of an introductory tutorial, I will be providing you with links to all the information you'll need so that you'll be equipped to take on just about any network/internet related tasks.

When it comes to this tutorial, the example program supplied should also work in linux (with perhaps some minimal changes) since linux sockets work pretty much the same way as Windows sockets. Since I don't have linux installed at the moment I can't give you these changes directly or know the discrepencies of Windows and Linux when it comes to sockets programming. If someone has played with sockets programming in linux with freebasic and knows these discrepencies (if any) please let me know via email and i'll be glad to add these to this tutorial. And now, let's get right into the core of winsock programming.

### FREEBASIC WINSOCK PROGRAMMING BASICS:

In most cases, when programming with winsock, there is a very simple order of things to follow. Since winsock typically talks to a server, no matter what type of interchange you'll be making with that server, you will be basically following the following order:

- Connect To The Server In Question:
  To do this, you'll essentially make a call to Winsock's Connect() function. This will require certain structures to be initialized with proper values
- Send Proper Command To Get Needed Data Or Perform Needed Task:
  In the general sense of the word, to send a command via winsock, you need to form a command string and send it to the server for processing. We'll see some of these commands in greater details in the example. These commands will vary depending on the connection type (HTTP, SMTP, FTP) and the task to be performed. At this point, more than one thing could be consecutively performed or requested say, in a loop, for example.
- Close The Connection To The Server:
  Of course, just like file manipulation, it's a great idea to close whatever you open for very obvious reasons. This frees the server of your connection to it and allows it to work on other server requests.

It doesn't matter the job to be done via winsock, there's no command that automatically opens or closes things for you so it will be a simple question of remember to open, perform the request or task and close. Just be warned that if you don't close your connections after a while of opening new connections, you (or you with other people) could overflow the server and hence freeze on your side and slow down the server dramatically for other users so just pay a little attention and show a little consideration when doing internet related network programming.

### MAKING SENSE OF THE PROTOCOLS AND COMMANDS:

The commands in question, as I mentionned, differ depending on the protocol used. Each type of connection allows different sets of commands and as such, I will enumerate here the four most used protocols with links to list of commands so you get an idea of what can be done under these different protocols. The protocols are:

- HTTP (HyperText Transfer Protocol:
  The name says it all here. HTTP is a protocol originally created to transfer html files. It is a request/response protocol between clients and servers. Here is the Wiki Page on the HTTP protocol.
- FTP (File Transfer Protocol):
  FTP is typically used in internet access that will be transfering files from and to a given server. The server, of course, needs to offer FTP access in order for FTP commands to work. Here's the Wiki Page for the FTP protocol.
- SMTP (Simple Mail Transfer Protocol):
  As you might have guessed, this protocol is for email related functionality and requests. Whether you are receiving or sending mail, this will be the protocol to use. Here's the Wiki Page on the SMTP protocol.
- TCP/IP (Transmission Control Protocol/Internet Protocol):
  I used TCP/IP here because it's the most renouned name for it, but today, it seems to be called the Internet Protocol Suite now. It now pretty much emalglobates the three other protocols above and is designed to work both for networks and internet related functionalities. Here's the Wiki Page on the TCP/IP protocol.

Of course, there are other protocols, but in all honesty, the other protocols are either used less and less or practically dissapeared from the map. When you think about it, there's not much more you'd be doing on the internet (except chatting or group gaming which is done with TCP/IP anyways) aside viewing websites, sending and receiving emails and uploading or downloading files.

FreeBASIC comes with a special library for winsock and sockets programming. In the next section we'll talk about it however, we'll limit ourselves to just what we need for this tutorial or the next section would be way passed the scope of this tutorial. So then, let's get right to it.

### THE DREADED WINSOCK.BI INCLUDE FILE:

I'm not sure if any of you have looked at the "winsock.bi" file but you might notice that it's 17kb in size, has a lot of defines, user defined types, constants and sub and function declaration. There is also the winsock2.bi file which stands at a whopping 48kb, has alot more defines, constants, user defined types and subs and functions declarations. In otherwords, it has alot more definitions and declarations that we need for a first program. winsock.bi and winsock2.bi are located in your freebasic installation folder under the inc\win\ folder. If you want, you can take a look at them to get their full scope of definitions. However, for the purpose of this tutorial and your convenience, I've extracted the definitions and declarations that that we will be needing only.

Since these are extractions, I have not documented them per se, the most important thing to know here is that all these definitions are in winsock.bi and winsock2.bi. if you want a good complete reference on winsock programming, take a look at the Sockets.com which features everything you ever wanted to know about the subject and complete references to standards, protocols, function and sub references for winsock and reference lists and references for all RFC standards. sockets.com is by far the best website to use for anything winsock related, take a look and see for yourself how complete it is.

The Constant Definitions and Define Statements:

As you can see below, we don't need alot of constants here. we only have four defined here (note that winsock.bi has alot more because of the different types of internet protocols and connections that can be made) and for this tutorial it's really all we'll need. We defined a macro called MAKEWORD that essentially assures that the value return is of a valid USHORT type (0 to 65535 in range).

>     OPTION EXPLICIT

>     ' --------------------
>     '  Library Inclusions
>     ' --------------------
>     '#Include "winsock.bi"    <- Commented out for tutorial purposes,
>                               '  should be used instead in projects
>     #INCLIB "wsock32"

>     ' ------------------------------------------------------------------
>     '  Constants and defines extracted from winsock.bi for this example
>     ' ------------------------------------------------------------------
>     CONST AF_Inet     = 2
>     CONST Sock_Stream = 1
>     CONST IPProto_TCP = 6
>     CONST NewLine     = CHR$(13)+CHR$(10)

>     #DEFINE MAKEWORD(a,b)      ((a) shl 8 or ((b) and &h000000FF))
>     #DEFINE WSADESCRIPTION_LEN 256
>     #DEFINE WSASYS_STATUS_LEN  128

The User Defined Types:

The user defined types shown here (seven of them) are shown here because they are used either in other structures (some structures have fields that are of other structure types) or as final structures to be used by the winsock related functions. Some of the names here are quite ambiguous and in my opinion could have been given much better and clearer names than those used here.

>     ' ---------------------------------------------------------------
>     '  User Defined Types extracted from winsock.bi for this example
>     ' ---------------------------------------------------------------
>     TYPE WSAData
>          wVersion         AS SHORT
>          wHighVersion     AS SHORT
>          szDescription    AS STRING * WSADESCRIPTION_LEN+1-1
>          szSystemStatus   AS STRING * WSASYS_STATUS_LEN+1-1
>          wMaxSockets      AS USHORT
>          wMaxUDPDG        AS USHORT
>          dwVendorInfo     AS BYTE PTR
>     END TYPE

>     TYPE HostEnt
>          H_Name           AS BYTE PTR
>          H_Aliases        AS BYTE PTR PTR
>          H_AddrType       AS SHORT
>          H_Length         AS SHORT
>          H_Addr_List      AS UINTEGER PTR PTR
>     END TYPE

>     TYPE S_Un_B_
>          S_B1             AS UBYTE
>          S_B2             AS UBYTE
>          S_B3             AS UBYTE
>          S_B4             AS UBYTE
>     END TYPE

>     TYPE S_Un_W_
>          S_W1             AS USHORT
>          S_W2             AS USHORT
>     END TYPE

>     UNION In_Addr
>           S_Un_B          AS S_Un_B_
>           S_Un_W          AS S_Un_W_
>           S_Addr          AS UINTEGER
>     END UNION

>     Type SockAddr_In
>          Sin_Family       AS SHORT
>          Sin_Port         AS USHORT
>          Sin_Addr         As In_Addr
>          Sin_Zero(0 TO 7) AS BYTE
>     End Type

>     Type SockAddr
>          SA_Family        AS SHORT
>          SA_Zero(0 TO 13) AS BYTE
>     END TYPE

The A.P.I. Function Declarations:

Again, winsock.bi and winsock2.bi have a whole lot more API function declarations than those shown here. However, for the sake of this tutorial, once again, I merely included the functions that we will need. the WS prefix you can see in most of these functions are to indentify that the functions are WinSock related.

>     ' ----------------------------------------------------------------------
>     '  API Function Declarations extracted from winsock.bi for this example
>     ' ----------------------------------------------------------------------
>     DECLARE FUNCTION WSAStartup _
>                  LIB "WSock32" _
>                ALIAS "WSAStartup" (BYVAL wVersionRequired AS SHORT, _
>                                    BYVAL lpWSAData        AS WSAData PTR) AS LONG

>     DECLARE FUNCTION WSAGetLastError _
>                  LIB "WSock32" _
>                ALIAS "WSAGetLastError" () AS LONG

>     DECLARE FUNCTION WSACleanup _
>                  LIB "WSock32" _
>                ALIAS "WSACleanup" () AS LONG

>     DECLARE FUNCTION Socket _
>                  LIB "WSock32" _
>                ALIAS "socket" (BYVAL AF       AS LONG, _
>                                BYVAL S_Type   AS LONG, _
>                                BYVAL Protocol AS LONG) AS LONG

>     DECLARE FUNCTION CloseSocket _
>                  LIB "WSock32" _
>                ALIAS "closesocket" (BYVAL S AS LONG) AS LONG

>     DECLARE FUNCTION Connect _
>                  LIB "WSock32" _
>                ALIAS "connect" (BYVAL AS LONG, _
>                                 BYVAL AS SockAddr PTR, _
>                                 BYVAL AS LONG) AS LONG

>     DECLARE FUNCTION HTons _
>                  LIB "WSock32" _
>                ALIAS "htons" (BYVAL HostShort AS USHORT) AS USHORT

>     DECLARE FUNCTION GetHostByName _
>                  LIB "WSock32" _
>                ALIAS "gethostbyname" (BYVAL szHost AS STRING) AS HostEnt PTR

>     DECLARE FUNCTION Send _
>                  LIB "WSock32" _
>                ALIAS "send" (BYVAL SocketID  AS LONG, _
>                              BYVAL BufferPtr AS LONG, _
>                              BYVAL BufLen    AS LONG, _
>                              BYVAL Flags     AS LONG) AS LONG

>     DECLARE FUNCTION Recv _
>                  LIB "WSock32" _
>                ALIAS "recv" (BYVAL SocketID  AS LONG, _
>                              BYVAL BufferPtr AS LONG, _
>                              BYVAL BufLen    AS LONG, _
>                              BYVAL Flags     AS LONG) AS LONG

Now, take a look at the following 2 functions. You'll notice they are quite empty (1 line each) and well I thought I'd explain why I didn't just use the WS related functions themselves. Usually, a winsock "session" needs to have an initialization/creation section prior to the work to be done, and a closing section after, one never knows what might be needed when creating or closing an internet connection. Therefore, I've created these two functions as a skeleton app. In your projects, you might need to create variables, assign some values, to different things before you execute your task and keeping this initialization material in one function is a great way to keep the code organized and clear. Same goes for closing or terminating a winsock session. So think of these two functions as a template to follow. But again, my style is my style and you're more than welcome to use it, or not, depends on what you need initialized and prepared before you perform your work as well as what needs to be closed and released from resources when the work is done.

>     '====================================================
>     ' StartSockets gets a WSAData structure ready to be
>     ' used in the rest of the program.
>     '====================================================
>     FUNCTION StartSockets() AS LONG

>         DIM WSAInfo AS WSAData

>         WSAStartup(MakeWord(1,1), @WSAInfo)

>     END FUNCTION

>     ' ====================================================
>     '  EndSockets clears resources used by StartSockets
>     ' ====================================================
>     FUNCTION EndSockets() As Long

>         WSACleanup()

>     END FUNCTION

Next on the list, take a look at the ConnectToURL function below. This is where "the work" actually happens. I have commented the code here so you see what each part does but the basic idea is to perform the following (once the socket is opened):
1. Retrieve the URL's host
2. Create the URL's socket
3. Connect to the URL
4. Prepare HTTP GET request and send it to throught the socket
5. Retrieve the contents
6. Display the retrieved contents on the screen

>     ' ====================================================
>     '  NAME:         ConnectToURL()
>     '  PARAMETERS:   BYVAL URL AS STRING
>     '  RETURN VALUE: A LONG typed value
>     '  ASSUMES:      URL to be a valid website URL
>     ' ----------------------------------------------------
>     '  DESCRIPTION:  This function performs the actual
>     '                work of this demonstration.  it will
>     '                connect to the URL passed as its
>     '                parameter and retrieve and display
>     '                some information about the URL.
>     ' ====================================================
>     FUNCTION ConnectToURL(BYVAL URL AS STRING) AS LONG

>         ' ----------------
>         '  Work Variables
>         ' ----------------
>         DIM URLHost       AS HostEnt PTR
>         DIM URLSocket     AS SockAddr_In
>         DIM URLSocketID   AS UINTEGER
>         DIM Connection    AS LONG
>         DIM Message       AS STRING
>         DIM Buffer        AS STRING
>         DIM BufferReceive AS ZSTRING *1001
>         DIM BytesReceived AS LONG

>         ' ---------------------
>         '  Retreive URL's host
>         ' ---------------------
>         URLHost = GetHostByName(URL)
>         ' ---------------------
>         '  Create URL's Socket
>         ' ---------------------
>         WITH URLSocket
>              .Sin_Family      = AF_Inet
>              .Sin_Port        = HTons(80)
>              .Sin_Addr.S_Addr = **URLHost->H_Addr_List
>         END WITH
>         ' -------------------
>         '  Create The Socket
>         ' -------------------
>         URLSocketID = Socket(AF_Inet, Sock_Stream, IPProto_TCP)
>         ' --------------------
>         '  Connect To The URL
>         ' --------------------
>         Connection  = Connect(URLSocketID, @URLSocket, LEN(URLSocket))
>         ConnectURL  = URLSocketID
>         ' -------------------------------------------------------------
>         '  Prepare HTTP GET request and send it to throught the socket
>         ' -------------------------------------------------------------
>         Message     = "GET / HTTP/1.0" + NewLine _
>                       + "Host: " + URL + NewLine _
>                       + "User-Agent: MystikShadows/1.0" + NewLine + NewLine
>         Send(URLSocketID, STRPTR(Message), LEN(Message), 0)
>         ' ---------------
>         '  Retrieve File
>         ' ---------------
>          BytesReceived = Recv(URLSocketID, STRPTR(BufferReceive), 1000, 0)
>          WHILE BytesReceived > 0
>                Buffer = Buffer + LEFT$(BufferReceive, BytesReceived)
>                BytesReceived = Recv(URLSocketID, STRPTR(BufferReceive), 1000, 0)
>          WEND
>          ' --------------------------------------------
>          '  Display received file and info to the user
>          ' --------------------------------------------
>          PRINT Buffer

>     END FUNCTION

With all of these created, it makes the main part of the program quite short. All it does now is declare a variable called Connection of type LONG, calls the StartSockets() function (with whatever initialization code you may need), calls the ConnectToURL() function which performs the actual task and finally calls the EndSockets() function to close what's been opened (and release resources as needed by your projects).

>     '==========================
>     ' MAIN PART OF THE PROGRAM
>     '==========================
>     DIM Connection AS LONG

>     StartSockets()
>     Connection = ConnectToURL("www.ascii-world.com")
>     EndSockets()

>     SLEEP

And that just about covers it really. This program will perform the intended work which is to connect to http://www.ascii-world.com and display information and contents about the URL. Note that you can change the call to ConnectToURL to supply other URL addresses to see what they will show you. Don't worry, you don't have to type (or cut and paste) all that in, here's a link to the sockets.bas so you can just download the file and compile it for yourself. Here is what the program produced with the ascii-world URL.

### AND TO CONCLUDE THIS TUTORIAL:

There you have it, we are at the end of this winsock programming tutorial in FreeBASIC. I think that as an introduction, it covered alot of grounds and gave you a good start on your own winsock projects. As far as winsock itself is concerned, the functions needed are all present in winsock.bi and winsock2.bi. Don't forget to consult the links I provide in this tutorial to learn everything that you can do with winsock and how to do them as well. The references to the protocols will tell you which you should use on a given wonsick project and also have valid protocol commands for you so you can learn HTTP, FTP, SMTP programming in all it's details. Winsock programming is by no means a simple subject. When looking at the example shown here we can see that it still takes quite a few steps to perform a very basic winsock related task. However, there's no denying the necessity of winsock programming whetehr you are creating an online game, or an application that can really benefit from a connection to some online resource. So I believe this should be enough to get you curious to see just what else can be done with winsock.

Remember, as always, that i'm always opened to comments, suggestions, ideas, constructive criticism and questions from you, just email me with anything you want to share with me about winsock programming. I'll be happy to answer questions, and bring suggestions and help to your winsock projects as well. If you'd like me to write on other winsock related subjects just let me know either by emailing me (see the email address below) or on the Official QB Express Article request thread and I'll see what I can do. Until next time, happy reading, and coding.

MystikShadows
Stéphane Richard
mystikshadows@gmail.com