您的位置:首页 > 理论基础 > 计算机网络

Programming TCP/IP Windows Sockets in C++

2014-10-25 17:38 477 查看

Programming TCP/IP Windows Sockets in C++

【原文下载】 http://download.csdn.net/detail/a569507680/8081099

There really is not a lot of material onthis subject, I believe, that explains the use of Windows sockets sufficientlyenough for a beginner to understand and begin to program them. I still rememberthe hassle that I went through trying to find a proper tutorial
that didn’tleave me hanging with many questions after I started programming with themmyself. That was a long time ago now, and it was quite a challenge for me toprogram my first application that could communicate with other computers overthe Internet – even
though my first introduction to sockets was through VisualBasic; a high-level and very user-friendly programming language. Now that Ihave long since switched to the more powerful C++, I rapidly found that thelabor I had expended to code sockets in VB was nothing
compared to whatawaited!



Thankfully, after many hours searchingvarious web pages on the Internet, I was able to collect all the bits andpieces, and finally compile my first telnet program in C++. My goal is tocollect all the necessary data in one place; right here, so the reader
doesn’thave to recollect all the data over the Internet like I had to. Thus, I presentthis tutorial in hopes that it alone will be sufficient information to beginprogramming.



Before webegin, you will need to include winsock.h and linklibws2_32.ato your project in order to use the API that are necessary for TCP/IP. If thisis not possible, useLoadLibrary() to loadws2_32.dll
at runtime,or some similar method.



All thecode in this article was written and tested using Bloodshed Dev-C++ 4.9.8.0;but generally, it should work with any compiler with minimal modifications.



What the Heck are Threads, Ports, and Sockets?

Actually, we can use the word-picture presentedto us by the name socket in a similar fashion to illustrate what theyare and how they work. In an actual mechanical socket, you may recall that itis the female orreceiving end of a connection.
A thread is asymbolic name for a connection between your computer and a remote computer, anda thread is connected to a socket.



In case I’ve lost you with all that properterminology, you might think of a thread as an actual, physical, sewing-typethread stretched from one computer to the other, as the common analogy goes. Inorder for the threads to be attached to each computer, however,
there must be areceiving object that attaches to the threads, and these are called sockets.



A socket can be opened on any port;which is simply a unique number to distinguish it from other threads, becausemore than just one connection can be made on the same computer. A few of theseports have been set aside to serve a specific purpose.
Beyond these ports,there are quite a large number of other ports that can be used for anything andeverything: over 6,000, actually. A few commonly used ports are listed belowwith their corresponding services:



Port

Service

7

Ping

13

Time

15

Netstat

22

SSH

23

Telnet (default)

25

SMTP (Send mail)

43

Whois (Query information)

79

Finger (Query server information)

80

HTTP (Web pages)

110

POP (Receive mail)

119

NNTP

513

CLOGIN (Used for IP spoofing)

There are many more ports used for specificpurposes that are not shown here. Typically, though, if you wish to use a portthat has no specific assigned service, any port from 1,000 to 6,535 should bejust fine. Of course, if instead you want to listen in on
messages sent to andfrom service ports, you can do that too.



Are you connected to the Internet now?Let’s say you are, and you have Internet Explorer or some other web pageservice running, as well as AOL or some other chat program. On top of that (asif the connection wasn’t slow enough already) you’re trying to send
and receiveemail. What ports do you think are opened, sending and receiving data?



Internet Explorer (etc.) sends and receives data via port 80
AOL and other instant messaging programs usually like to hang out in the higher unassigned ports up in the thousands to be safe from interference. Each chat program varies, as there is no specific “chat” service and multiple messaging programs may run at
the same time
When you’re sending your email, you and the remote mail server are communicating using port 25
And, when you receive email, your mail client (such as Microsoft Outlook) uses port 110 to retrieve your mail from the mail server



And onward extends the list.



It’s not enough just to know what portnumber we’re using, obviously; we need to know what remote computer/serverwe’re connecting to. Just like we find out the home address of the people wevisit before we get in the car, we have to know theIP address
of thehost we are connecting to, if we are connecting and not just listening (a chatprogram needs to be able to do both).



An IP address is an identification numberthat is assigned to each computer on the network, and consists of 4 sets ofdigits separated by periods. You can view your IP address by runningipconfig.exeat the MSDOS prompt.



For theexamples shown throughout this tutorial, we will be using what is called theloop-backaddress to test our chat program without being connected to the Internet.This address is127.0.0.1. Whenever you try to make a connection
to thisIP, the computer loops the request back to you computer and attempts to locatea server on the specified port. That way, you can have the server and clientrunning on the same computer. Once you decide to connect to other remotecomputers, and you’ve worked
the bugs out of your chat program, you will needto get the unique IP address of each to communicate with them over theInternet.



Because we as humans are very capable offorgetting things, and because we couldn’t possibly hope to remember a bunch ofnumbers for every web site we visit, some smart individuals came up thewonderful idea ofdomain names. Now, we have neat little
names like www.yahoo.com andwww.cia.govthat stand for IP addresses that aremuch easier to remember than clunkysets
of digits. When you type one of these names in your browser window, the IPaddress for that domain name is looked up via arouter, and once it isobtained (or the host is
resolved), the browser can contact the serverresiding at that address.



For example, let’s say I call an operatorbecause I can’t remember my girlfriend’s phone number (fat chance). So, I justtell the operator what her name is (and a few other details, but that’s notimportant) and she happily gives me the digits. That’s kind
of what happenswhen a request is made for an IP address of any domain name.



We have two API that accomplish this task.It’s a good idea to make sure and check to see if whoever uses you programtypes a domain name instead of an IP address, so your program can look up thecorrect IP address before continuing. Most people, anyway, won’t
want toremember any IP addresses, so most likely you’ll need to translate domain namesinto IP addresses before you can establish a connection – which requires thatthe computer must be connected to the Internet. Then, once you have theaddress, you’re all set
to connect.



//Return the IP address of a domain name

DECLARE_STDCALL_P(structhostent *) gethostbyname(const char*);



//Convert a string address (i.e., “127.0.0.1”) to an IP address.Note that this function returns the address into the correct byte order for usso that we do not need to do any conversions (see next section)

unsignedlong PASCAL inet_addr(const char*);

Byte Order

Just when you thought all thisthread-socket stuff was going to be simple and easy, we have to startdiscussing byte order. This is because Intel computers and network protocolsuse reversed byte ordering from each other, and we have to covert each port andIP
address to network byte order before we send it; else we’ll have a big mixup. Port 25, when not reversed, will not end up being port 25 at all. So, wehave to make sure we’re speaking the same language as the server when weattempt to communicate with it.



Thankfully, we don’t have to code all theconversion functions manually; as Microsoft kindly provides us with a few APIto do this as well. The four functions that are used to change the byte orderof an IP or port number are as follows:



u_longPASCAL htonl(u_long); //Host to network long

u_longPASCAL ntohl(u_long); //Network to host long



u_shortPASCAL htons(u_short); //Host to network short

u_shortPASCAL ntohs(u_short); //Network to host short



Remember! The host computer isthe computer that listens for and invites connections to it, and thenetworkcomputer is the visitor that connects to the host.



So, for example, before we specify whichport we are going to listen on or connect to, we’ll have to use thehtons()function to convert the number to network byte order. Note that after usinginet_addr()to convert a string
IP address to the required form, we will be returned theaddress in the correct network order, eliminating the need to evokehtonl().An easy way to differentiate betweenhtons() andhtonl() is tothink of the port
number as the shorter number, and the IP as the longer number(which is true – an IP address consists of 4 sets of up to three digitsseparated by periods, versus a single port number).

Firing Up Winsock

OK, now that we’ve finally covered thebasics, hopefully you are starting to see light at the end of the tunnel and wecan move on. Don’t worry if you don’t understand every aspect of the procedure,for many supplementary facts will be brought to light as we
progress.



The first step to programming with windowssockets (A.K.A Winsock) is starting up the Winsock API. There are twoversions of Winsock; version one is the older, limited version; and version 2is the latest edition and is therefore the version we prefer
to specify.



#define SCK_VERSION1 0x0101

#define SCK_VERSION2 0x0202



intPASCAL WSAStartup(WORD,LPWSADATA);

intPASCAL WSACleanup(void);



//This typedef will be filled out when the functionreturns

//with information about the Winsock version

typedefstruct WSAData {

WORD wVersion;

WORD wHighVersion;

char szDescription[WSADESCRIPTION_LEN+1];

char szSystemStatus[WSASYS_STATUS_LEN+1];

unsigned short iMaxSockets;

unsigned short iMaxUdpDg;

char * lpVendorInfo;

}WSADATA;

typedefWSADATA *LPWSADATA;



You should only need to call thesefunctions once each, the former when you initialize Winsock, and the latterwhen you are finished. Don’t close down Winsock until you are finished, though,as doing so would cancel any connections that your program has initiated
or anyports that you are listening on.



Initializing a Socket

We understand how sockets work now,hopefully, but up until now we had no idea how to initialize them. The correctparameters must be filled out and passed to a handy API call that begins thesocket (hopefully). In this case, we are returned the handle to the
socket thatwe have created. This handle is very “handy” and we must keep it on hand tomanipulate the socket’s activity.



When you are all finished doing your dirtywork, it is considered proper programming practice to shut down any socketsthat you have opened before your program exits. Of course, when it does, allthe ties and connections it has will be forcibly shut down, including
anysockets, but it’s better to shut them down the graceful way with closesocket().You will need to pass the socket’s handle to this API when you call it.





//There are many more options than the ones defined here, to seethem

//browse the winsock2.h header file



#define SOCK_STREAM 1

#define SOCK_DGRAM 2

#define SOCK_RAW 3



#define AF_INET 2



#define IPPROTO_TCP 6



SOCKETPASCAL socket(int,int,int);

intPASCAL closesocket(SOCKET);



When creating a socket, you will need topass the address family, sockettype, and theprotocol type.Unless you’re doing some special (or odd) work, which is beyond the scope ofthis report, you should typically just passAF_INET
as the defaultaddress family. This parameter specifies how the computer addresses will beinterpreted.



There is more than just one type of socket;actually, there are many more. Three of the most common ones include: Raw Sockets,Stream Sockets, and Datagram Sockets. Stream sockets, however, are what we areusing in this tutorial, since we are dealing with TCP
protocols, so we willspecify SOCK_STREAM as the second parameter tosocket().



We’re close, so close! We’ve got the “nittygritty” stuff done and over with, so let’s move on the more exiting parts ofWinsock programming.



Connecting to a Remote Host (Acting as the Client)

Let’s try out what we’ve gone over with asimple program that can connect to a remote computer. Doing this will help youto understand much better how everything works, and helps to preventinformation overload!



You’ll need to fill out information aboutthe remote host that you are connecting to, and then pass a pointer to thisstructure to the magic function,connect(). This structure and the APIare listed below. Note that thesin_zero
parameter is unneeded and isthus left blank.



structsockaddr_in {

short sin_family;

u_short sin_port;

struct in_addr sin_addr;

char sin_zero[8];

};



intPASCAL connect(SOCKET,const struct sockaddr*,int);



I highly recommend that you type in all ofthe examples in this report by hand, instead of copying and pasting it intoyour compiler. While I know that doing so will slow you up, I am confident andknow from experience that you will learn the processmuch
better thatway than if you copy and paste the code.





//CONNECT TO REMOTE HOST(CLIENT APPLICATION)

//Include the needed headerfiles.

//Don’t forget to link libws2_32.ato your program as well

#include <winsock.h>



SOCKET s; //Sockethandle



//CONNECTTOHOST – Connects to aremote host

boolConnectToHost(int PortNo, char* IPAddress)

{

//Start up Winsock…

WSADATAwsadata;



interror = WSAStartup(0x0202, &wsadata);



//Did something happen?

if(error)

return false;



//Did we get the right Winsock version?

If(wssadata.wVersion != 0x0202)

{

WSACleanup(); //Cleanup Winsock

return false;

}



//Fill out the information needed to initialize a socket…

SOCKADDR_INtarget; //Socket address information



target.sin_family= AF_INET; // address family Internet

target.sin_port= htons (PortNo); //Port to connect on

target.sin_addr.s_addr= inet_addr (IPAddress); //Target IP



s =socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); //Createsocket

if(s == INVALID_SOCKET)

{

return false; //Couldn’t create the socket

}



//Try connecting...

if(connect(s, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR)

{

return false; //Couldn’t connect

}

else

return true; //Success

}



//CLOSECONNECTION – shuts downthe socket and closes any connection on it

voidCloseConnection ()

{

//Close the socket if it exists

if(s)

closesocket(s);



WSACleanup();//Clean up Winsock

}



Before you move on, type this code up andgive it a try.



Receiving Connections – Acting as a Server

Now that you’vehad a feel for what it’s like to connect to a remote computer, it’s time toplay theserver role; so remote computers can connect to you. To dothis, we canlisten on any port and await an incoming connection. Asalways, we use
a few handy API calls:



intPASCAL bind(SOCKET,const struct sockaddr*,int); //bind toa socket

intPASCAL listen(SOCKET,int); //Listen for an incoming connection



//Accepta connection request

SOCKETPASCAL accept(SOCKET,struct sockaddr*,int*);



When you act asthe server, you can receive requests for a connection on the port you arelistening on: say, for example, a remote computer wants to chat with yourcomputer, it will first ask your server whether or not it wants to establish aconnection. In
order for a connection to be made, your server must accept()the connection request. Note that theserver decides whether or not toestablish the connection. Finally, both computers are connected and canexchange data.



Although the listen()function is the easiest way to listen on a port and act as the server, it isnot the most desirable. You will quickly find out when you attempt it that yourprogram will freeze until an incoming connection is made, becauselisten()is
a blocking function – it can only perform one task at a time, andwillnot return until a connection is pending. This is definitely a problem, butthere are a few solutions for it. First, if you are familiar withmulti-threaded applications (note
that we arenot talking about TCPthreads here), then you can place the server code on a separate thread that,when started, will not freeze the entire program and the efficiency of theparent program will thus not be impeded. This is really more of a
pain that itneeds to be; as you could just replace the listen() function withasynchronoussockets. If I’ve caught your attention with that important-sounding name, youcan skip ahead to the next section if you like, but I recommend
that you stickwith me here and learn the fundamentals. We’ll spiff up our code later; but fornow, let’s focus on the bare essentials.



Before you caneven think about listening on a port, you must:



Initialize Winsock (we discussed this before, remember)
Start up a socket and make sure it returns a nonzero value, which signifies success and is the handle to the socket
Fill out the SOCKADDR_IN structure with the necessary data, including the address family, port, and IP address.
Use bind() to bind the socket to a specific IP address (if you specifiedinet_addr(“0.0.0.0”) or
htonl(INADDR_ANY) as thesin_addr section ofSOCKADDR_IN, you can bind to any IP address)



At this point,if all has gone according to plan, you’re all set to call
listen()
andspy to your heart’s content.



The firstparameter of listen() must be the handle to a socket that you have previouslyinitialized. Of course, whatever port this socket is attached to is the portthat you will be listening on. You can then specify, with the next and finalparameter,
how many remote computers can communicate with your server at thesame time. Generally, however, unless you want to exclude all but one or a fewconnections, we just passSOMAXCONN (SOcket MAX CONNection) as the finalparameter tolisten().
If the socket is up and working fine, all shouldgo well, and when a connection request received,listen() will return.This is your clue to callaccept(), if you wish to establish aconnection.



#include<windows.h>

#include<winsock.h>



SOCKETs;

WSADATAw;



//LISTENONPORT – Listens on a specifiedport for incoming connections //or data

intListenOnPort(int portno)

{

interror = WSAStartup (0x0202, &w);
// Fill in WSA info



if(error)

{

returnfalse; //For some reason we couldn’t startWinsock

}

if(w.wVersion != 0x0202) //Wrong Winsock version?

{

WSACleanup();

returnfalse;

}



SOCKADDR_INaddr; // The address structure for a TCP socket



addr.sin_family= AF_INET; //Address family

addr.sin_port= htons (portno); // Assign port to this socket



//Accept a connection from any IP using INADDR_ANY

//You could pass inet_addr(“0.0.0.0”) instead toaccomplish the //same thing. If you want only to watch for a connection from a//specific IP, specify that instead.

addr.sin_addr.s_addr= htonl (INADDR_ANY);



s= socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); // Create socket



if(s == INVALID_SOCKET)

{

returnfalse; //Don’t continue if we couldn’tcreate a //socket!!

}



if(bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)

{

//We couldn’t bind (this willhappen if you try to bind to //the same socket more than once)

returnfalse;

}



//Now we can start listening (allowing as many connections as//possible to be made at the same time using SOMAXCONN). You //could specifyany integer value equal to or lesser than //SOMAXCONN instead for custompurposes). The function
will not //return until a connection request is made

listen(s,SOMAXCONN);



//Don’t forget to clean up with CloseConnection()!

}



If you compile and run this code, asmentioned before, your program will freeze until a connection request is made.You could cause this connection request by, for example, trying atelnetconnection. The connection will inevitably
fail, or course, because theconnection will not beaccepted, but you will causelisten() toreturn and your program will resurrect from the land of the dead. You can trythis by typingtelnet 127.0.0.1port_number
at the MSDOS commandprompt (replace “port_number” with the port that your server is listening on).



Asynchronous Sockets

Because using blocking functions such as listen()is so impractical and such a pain, let’s go ahead and before we move on discussasynchronous sockets. I mentioned these earlier on, and promisedyou I’d show you how they work.



C++ gives us an advantage here that mosthigh-level programming languages do not; namely, because we don’t have to go tothe extra length ofsub-classing the parent window before we can useasynchronous sockets. It’s already done for us, so all we really
have to do isadd the handling code into the message handler. This is because asynchronoussockets, as you will see, depend on being able to send your program messageswhen a connection request is made, data is being received, etc. This enables itto wait silently
in the background without disturbing your parent program orimpeding productivity, as it only communicates when necessary. There is arelatively small price to pay, too, for it really doesn’t take much additionalcoding. Understanding how it all works might take
a little while, but you’lldefinitely be pleased that you took the time to understand asynchronoussockets. It’ll save you a lot of trouble in the long run.



Instead of having to rework and modify allthe code that we have written up to this point, making a socket asynchronoussimply requires an additional line of code after thelisten() function.Of course, your message handler needs to be ready
to accept the followingmessages:



FD_ACCEPT: If your application is acting as the client (i.e., you are attempting to connect to a remote host usingconnect()), you will receive this message when a connection request is being made. Should you choose to do
so, the following message will be sent:
FD_CONNECT: Signifies that a connection has been successfully made
FD_READ: We’ve got incoming data from the remote computer. We’ll learn how to deal with this later on.
FD_CLOSE: The remote host disconnected, so we lost the connection.



These values will be sent in the lParamparameter of your message handler. I’ll show you exactly where to put them in aminute; but first, we need to understand the parameters of the API call we’llbe using to set our socket to asynchronous
mode:



//Switch the socket to a non-blocking asynchronous one

intPASCAL WSAAsyncSelect(SOCKET,HWND,u_int,long);



The first parameter, obviously, asks for ahandle to our socket, and the second requires the handle to our parent window.This is necessary so that it send the messages to the correct window! The thirdparameter, as you can see, accepts an integer value, for
which you will specifya unique notification number. When any message is sent to your program’smessage handler, whatever number you specify here will also be sent. Thus, youwould code your message handler to wait for the identification number, andthendetermine
what type of notification has been sent. I know this is confusing, sohopefully a glance at the following source code will shed a little light on thesubject:



#define MY_MESSAGE_NOTIFICATION 1048 //Custom notification message



//This is our messagehandler/window procedure

LRESULT CALLBACK WndProc(HWND hwnd, UINTmessage, WPARAM wParam, LPARAM lParam)

{

switch(message) //handle the messages

{

caseMY_MESSAGE_NOTIFICATION: //Is a message being sent?

{

switch(lParam) //If so, which one is it?

{

caseFD_ACCEPT:

//Connectionrequest was made

break;



caseFD_CONNECT:

//Connection was madesuccessfully

break;



caseFD_READ:

//Incoming data;get ready to receive

break;



caseFD_CLOSE:

//Lost the connection

break;

}

}

break;



//Other normal window messages here…



default://The message doesn’t concern us

return DefWindowProc(hwnd,message, wParam, lParam);

}

break;

}



That’s not toobad, is it? Now that our handler is all set, we should append the followingline of code to functionListenOnPort(), afterlisten():



//The socket has been created



//IP address has been bound



//Function listen() has just been called…



//Set the socket to non-blocking asynchronous mode

//­hwnd is a valid handle to the program’s parent window

//Make sure you OR all the needed flags

WSAAsyncSelect(s, hwnd, MY_MESSAGE_NOTIFICATION, (FD_ACCEPT | FD_CONNECT | FD_READ |FD_CLOSE);



//And so forth…



If you followed the steps correctly, youshould have a server up and running. But how can you tell if you are reallylistening on a port? Well, there’s a handy tool that you might know about,called;netstat.exe, that ships with most versions
of Windows, and canaid us in determining what ports are open on our computer. To use it, typenetstat–anat the MSDOS command prompt, and you’ll see something to thiseffect, depending on which ports and services are open on your computer:



C:\Documentsand Settings\Cam>netstat -an



ActiveConnections



Proto Local Address ForeignAddress State

TCP 0.0.0.0:135 0.0.0.0:0 LISTENING

TCP 0.0.0.0:445 0.0.0.0:0 LISTENING

TCP 0.0.0.0:5225 0.0.0.0:0 LISTENING

TCP 0.0.0.0:5226 0.0.0.0:0 LISTENING

TCP 0.0.0.0:8008 0.0.0.0:0 LISTENING

TCP 127.0.0.1:1025 0.0.0.0:0 LISTENING

TCP 127.0.0.1:1035 127.0.0.1:5226 ESTABLISHED

TCP 127.0.0.1:5226 127.0.0.1:1035 ESTABLISHED

TCP 127.0.0.1:8005 0.0.0.0:0 LISTENING

UDP 0.0.0.0:445 *:*

UDP 0.0.0.0:500 *:*

UDP 0.0.0.0:4500 *:*

UDP 127.0.0.1:123 *:*

UDP 127.0.0.1:1031 *:*

UDP 127.0.0.1:1032 *:*

UDP 127.0.0.1:1900 *:*



C:\Documentsand Settings\Cam>



If your server is working correctly, youshould see under Local Address something like, “0.0.0.0:Port#,”wherePort# is the port that you are listening on, in a LISTENING state.Incidentally, if you forget to usehtons()
to convert the port number,you might find a new port has been opened, but it will be on a completelydifferent port than what you expected.



Don’t worry if it takes you a couple oftries to get everything working right; it happens to all of us. You’ll get itwith a couple of tries. (Of course, if you try without avail for a coupleweeks, burn this report and forget who wrote it!)



Sending and Receiving Data

Up to this section, all you’ve got for aserver is a deaf mute! Which, not surprisingly, does not do you a lot of goodin the real world. So, let’s take a look at how we can communicate properly andeffectively with any computer that decided to chat with us.
As always, a fewAPI calls come to the rescue when we’re stumped:



//Send text data to a remote computer

intPASCAL send(SOCKET,const char*,int,int);



//Receive incoming text from a remote computer

intPASCAL recv(SOCKET,char*,int,int);



//Advanced functions that allow you to communicate exclusivelywith a //certain computer when multiple computers are connected to the same//server

intPASCAL sendto(SOCKET,const char*,int,int,conststruct sockaddr*,int);

intPASCAL recvfrom(SOCKET,char*,int,int,structsockaddr*,int*);



If you’re not using an asynchronousserver, then you’ll have to put therecv() function in a timer function,that constantly checks for incoming data – not so elegant of a solution, to saythe least. If, on the other hand, you’ve done
the smart thing and set up anasynchronous server, then all you have to do is put yourrecv() codeinside
FD_READ in your message handler. When there’s incoming data,you’ll be notified. Can’t get any easier than that!



When we do detect activity, a buffer mustbe created to hold it, and then a pointer to the buffer passed torecv().After the function returns, the text should have been dutifully placed in ourbuffer just itching to be displayed. Check out
the source code:



//…

caseFD_READ:

{

charbuffer[80];

memset(buffer,0, sizeof(buffer));
//Clear the buffer



//Put the incoming text into our buffer

recv(s, buffer, sizeof(buffer)-1, 0);



//Do something smart with the text in buffer

//You could display it in a textbox, or use:



//MessageBox(hwnd, Buffer, “Captured Text…”, MB_OK);

}

break;

//…



Now that you can receive incoming text fromthe remote computer or server, all that our server lacks is the ability toreply, orsend data to the remote computer. This is probably the mostsimple and self-evident process in Winsock programming, but
if you’re like meand like to have every step spelled out for you, here’s how to usesend()correctly:



char*szpText;



//Allocate memory for the text in your Text Edit, retrieve thetext,

//(see the source code for this) and then pass a pointer to it…



send(s,szpText, len_of_text, 0);



For brevity’s sake, the above snippet ofcode is just a skeleton to give you a general idea of howsend() isused. To see the entire code, please download theexample source codethat comes along with this tutorial.



On a more advanced note, sometimes thesimple send() and
receive()
functions just aren’t enough to dowhat you’re looking for. This happens when you have multiple connections at thesame time from different sources (remember when we calledlisten(), wepassedSOMAXCONN to allow
the maximum number of connections possible),and you need to send data toone particular computer, and notallof them. If you’re uncommonly sharp, you may have noticed two extra API belowsend()andreceive() (extra
credit if you did!);sendto() andreceivefrom().These two API allow you to communicate with any one remote computer withouttipping your hand to everyone else that is connected. There is an extraparameter that accepts a pointer
to asockaddr_in structure in theseadvanced functions, which you can use to specify the IP address of any remotecomputer that you want to communicate with exclusively. This is an importantskill to know if you are building a full-fledged chat
program, or somethingsimilar, but beyond giving you the basic idea of how these functions work, I’lllet you figure them out on your own. (Don’t you hate it when authors say that? Usuallyit’s because we don’t have the slightest clue ourselves… but really, itshouldn’t
take much to implement them if you decide that you need to.)



Some Final Notes

Well, by now you should have a decentunderstanding of Windows sockets – or a profound hatred of them – but at rate,if you’re looking for a much better explanation than I can give you here,please take a look at the example source code provided with this article.Practice
will do much more for you than reading any article.



Additionally, I have found that if you tryto copy and paste code, or just compiling someone else’s code you found on theInternet, you won’t come close to the level of understanding you will gain ifyou type in all the examples by hand yourself. A big pain,
I know! But if youtake the time to do it, you’ll save yourself a lot of trouble in the long run.



Have fun, and let me know what you think ofthis article by posting feedback.



This article (not including theaccompanying source code) is copyrighted © 2006 by the author, and cannot bemodified, sold, and redistributed for personal gain without prior explicitpermission from him. It is provided free of charge for the benefit of thepublic.
You are allowed, however, to make and distribute as many copies of itas you like, provided that you do not modify the original content in any way.Thanks!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: