⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 article711.asp.htm

📁 一个网络游戏程序编写的例子
💻 HTM
📖 第 1 页 / 共 5 页
字号:

//We'd create socket s somewhere in here

...

x = sizeof(addr);
recvfrom(s, &data, sizeof(data), 0, &addr, &x);

</PRE></BLOCKQUOTE>

<P><B>How to get your sockets to listen()</B>

<P>Aside from making them an offer that they can't refuse, the other way to
get your sockets to listen is to use the listen() function (and you call
this un-intuitive?). listen() has the main goal of getting a socket to
listen for connections, and, if a connection is attempted, to add it to
queue so that it can be processed and accepted by the accept() function (I
know that I'm starting to see a pattern, here...)

<P>In order for listen to have any meaning, two conditions must be met. First,
a socket must be bound to a port on the local host. This is, as has already
been discussed, achieved via the bind() function. Second, the socket must
not be connected to a remote host at the time that it is listening for a
connection. If you stop and think about it for a moment, this rather makes
sense.

<P>The first parameter of listen() is a socket descriptor of the socket which
is to listen for incoming connections. The second parameter is the size of
the backlog, or the queue to hold incoming connection requests, for the
socket. There are numerous and creative ways to describe the backlog size
parameter, but let it suffice to say that its maximum value is given by a
constant SOMAXCONN. For our purposes, we may as well use this constant,
although I highly doubt that (based upon the value of SOMAXCONN in Winsock
2) we will ever receive such a load of connections. The return value of
listen() is 0 if no error occurs, and otherwise is 0.

<BLOCKQUOTE><PRE><FONT FACE="courier new, fixedsys" SIZE="2" COLOR="#000088">
SOCKET s;

...

//create and bind socket s

...

listen(s, SOMAXCONN);

</PRE></BLOCKQUOTE>

<P>Before accept() can be used, it is of course logical that the socket we
wish to accept a connection on must be paying attention, i.e., listening.
accept() is almost exactly the same as connect(), except that the second
parameter, the pointer to a sockaddr_in structure, will get the address of
the remote host instead of hold it, and the third parameter, this time for
a worthy reason, is a pointer to an int that will get the length of the
address returned. Note that the third parameter, in accordance with correct
WinSock practices, should contain the sizeof the sockaddr_in structure on
calling accept().

<BLOCKQUOTE><PRE><FONT FACE="courier new, fixedsys" SIZE="2" COLOR="#000088">
SOCKET s;
struct sockaddr_in addr;
int x = sizeof(addr);
...

//create and bind socket s, then listen for connetions

...

accept(s, &addr, &x);

</PRE></BLOCKQUOTE>

<P><B>Blockage and Synchronicity</B>

<P>While the title of this section sounds rather like a prospective Tom Clancy
novel, it's really a somewhat important issue. Up until this point, we have
rather candidly ignored a fundamental question associated with all of the
functions that we have explored. Let's consider the example of the recv()
function. What would happen if there were no data to be received and we
called recv()? If the connection had been closed on the other end, recv()
would return politely and give us no data. However, if the connection is
still intact, and the problem is simply that no data exists to be received,
recv() would sit and wait for data to come in. This behavior of recv()
defines it as a blocking function, one that blocks other code in a program
from taking effect until it finishes. This is better stated by saying that
recv() is a synchronous function as opposed to an asynchronous function.

<P>In Berkley Sockets, this situation can be remedied by using the select()
function. select() will take as its parameters a set of arrays of sockets
to check for readability, the ability to write, error conditions, and other
great things of the sort. Then, when something happens on one of these
sockets, the event will be processed. This, while it worked fine and well
for BSD, is not a very elegant solution under the Win32 development
paradigm.

<P>As a direct consequence of this problem, WinSock introduced asynchronous
socket I/O functions that operate based upon the Windows messaging scheme.
For once, I have to give credit to Win32 for introducing a better way of
doing things.

<P>The WSAAsyncSelect() function is the "control center" for the WinSock
asynchronous socket support. It takes as its first parameter a socket
descriptor. Its second parameter is the handle of a window whose WindowProc
will receive control messages for the socket. The third parameter is very
cool: It allows one to specify what message will be sent to one's
WindowProc when an event does occur on a socket. The final parameter to
WSAAsyncSelect() is a set of flags for events that a message will be sent
on. Here's a table, straight from (well, slightly modified from) the
documentation. I've taken the liberty of removing what is useless for the
purposes of a game programmer.

<CENTER><P><B>WSAAsyncSelect Event Flags</B>
<TABLE WIDTH="90%" CELLSPACING=0 CELLPADDING=0 BORDER=3>
<TR><TD><B>Flag</B></TD><TD><B>Effect</B></TD></TR>
<TR><TD>FD_READ</TD><TD>Notifies the window proc that data are waiting for the socket</TD></TR>
<TR><TD>FD_WRITE</TD><TD>Notifies the window proc that data can be sent from the socket</TD></TR>
<TR><TD>FD_ACCEPT</TD><TD>Notifies the window proc on an incoming connection request</TD></TR>
<TR><TD>FD_CONNECT</TD><TD>Notifies the window proc on a connection having been completed</TD></TR>
<TR><TD>FD_CLOSE</TD><TD>Notifies the window proc when the socket closes</TD></TR>
</TABLE></CENTER>

<P>These can be combined as any bit-flags can. In the WindowProc, when the
socket event message is received, wParam will contain the socket to which
the event pertains, the low word of lParam will contain the event code
(from the table above), and the high word of lParam will contain whatever
errors if any have occurred.

<BLOCKQUOTE><PRE><FONT FACE="courier new, fixedsys" SIZE="2" COLOR="#000088">
#define SOCKET_EVENT_HAS_HAPPENED       25252

SOCKET s;
HWND mywnd;

...

//create s and mywnd

...

WSAAsyncSelect(s, mywnd, SOCKET_EVENT_HAS_HAPPENED, FD_READ | FD_WRITE | FD_ACCEPT);

</PRE></BLOCKQUOTE>

<P>Note that there are a lot of details involved in the WSAAsyncSelect()
function which I have neglected to cover. The basics discussed here are
sufficient to attain decent use of WSAAsyncSelect() without too many
problems. The rest is readily apparent from standard documentation.

<P>In addition to WSAAsyncSelect(), asynchronous counterparts of the name
service functions that we discussed a few sections back are also provided.
These also require no elucidation, as they are a logical extension of their
synchronous counterparts.

<P><B>Errors in WinSock</B>

<P>The error-handling scheme in WinSock operates generally based upon return
codes, but to figure out exactly what error has occurred, you need to call
the WSAGetLastError() function when the return value of a function is
non-zero (WSAStartup() would be the exception; it will return literally the
error that has occurred if anything goes wrong). WSAGetLastError() takes no
parameters and returns an integer error code.

<P><B>Cleaning up after yourself</B>

<P>Upon exiting a WinSock application, it is a good practice to call the
WSACleanup() function to clear up whatever you may have messed with in the
course of the application itself. You should also use the closesocket()
function, whose only parameter is a socket descriptor, to close a socket
when you're done with it. There is no disconnect() function in Berkley
Sockets; closing a socket is equivalent to disconnecting. However, in
WinSock, it is possible to call WSADisconnect(), and it is generally polite
to do so, but not required.

<P><B>What I didn't cover</B>
<P>There is a lot more material regarding WinSock. What I have covered in this tutorial is what you need to know to use WinSock effectively for the purposes of a game programmer. If you want to know everything about every cubic centimeter of it, my only recommendation would be to go out and buy a reference on it. I cannot humanly be expected to accurately document the 84 functions in WinSock 2 and give detailed descriptions of their practical applications.

<H1>Coda</H1>
<P>Well, I was going to present a demo with this article, but after it got to be over 50k, I decided that if it wasn't elicit enough, there's something wrong. I will use this space to send a message to the powers-that-be in article-writing: Help! I need assistance to complete this section. It took me a long time to put this documentation together, and it will take me even LONGER to cover the plethora of other standards out there. The present wish-list is for DirectPlay-related information and some demos. Anything you can throw together for this section would be greatly appreciated.

<H1>Disclaimers</H1>
<P>[1] If you don't like the use of the pronoun "his" in the general case, either append the English language or go back to the 13th century and bring Xena the Warrior Princess along.
<P>[2] If you read this tutorial and find any errors within it, you should report them. It's no loss of face for me; I'd rather have errors exposed and corrected than ingrained in the minds of readers, only to be struck out with a blunt object when they get into an argument in a bad neighborhood over the role of GGP or ICMP or something of the sort ten years down the line.
<P>[3] If you have any complaints or gripes with my style, my sense of humor, or anything relating to me or my existence, you can endulge yourself in fifty industrial-sized cans of "Beef-a-rooni", shove said complaints where the sun don't shine, and enrich the world with your beautiful music. Or, in short, write a better tutorial if you've got a problem with this one.
<P>[4] Any copyright or trademark infringement in this document is probably intentional, and while it would be only ethical to sue me, the legal costs that you would incur in the process would far exceed my net worth.
<P>Happy coding, finish that game, and send it over to GDW! ;)

<P ALIGN="center"><B><A HREF="javascript:if(confirm('http://www.gamedev.net/community/forums/topic.asp?key=featart&uid=711&forum_id=35&Topic_Title=The+Internet%2C+A+Summary+Introduction+to+TCP%2FIP%2C+and+Losing+Underwear  \n\n这个文件不能通过 Teleport Pro 取回, 因为 它被链接到离它的起始地址太远的地方. 如果你增大起始地址在其范围内的深度设置, 这个文件将进行列队等待取回.  \n\n你想从服务器打开它吗?'))window.location='http://www.gamedev.net/community/forums/topic.asp?key=featart&uid=711&forum_id=35&Topic_Title=The+Internet%2C+A+Summary+Introduction+to+TCP%2FIP%2C+and+Losing+Underwear'" tppabs="http://www.gamedev.net/community/forums/topic.asp?key=featart&uid=711&forum_id=35&Topic_Title=The+Internet%2C+A+Summary+Introduction+to+TCP%2FIP%2C+and+Losing+Underwear">Discuss this article in the forums</A></B></P>
<P>
<CENTER>
<!-- --> 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -