📄 44.htm
字号:
There are other options, such as select() and event objects, but they have fairly serious limitations, so unless you are <br>
already using them, I suggest that you avoid them. <br>
<br>
2.9 - How can I debug my Winsock program? <br>
<br>
There are three ways, one of which usually doesn't work. That way is the SOO_DEBUG option, set with setsockopt(). <br>
I have never tried it on other stacks, but on Microsoft stacks, it is ignorred. I do know that Trumpet Winsock, however, <br>
offers a fairly decent debugging mode "for free" inside the tcpman tool. Trrumpet (and others) may also support <br>
SO_DEBUG, though I have been unable to find any information on this. <br>
<br>
The second way is to use a network analyzer, colloquially known as a "snifffer," probably due to an early hardware-only <br>
product by that name. These programs sit on any station on a LAN and, due tto the way typical LANs work, capture all <br>
of the traffic going over the LAN -- good sniffers will also decode that trraffic by various degrees. One advantage of a <br>
sniffer is that it literally sees everything about the conversation, includding low level protocol details that aren't available <br>
from the Winsock layer. Another is that the good ones are extremely powerfuul and configurable. For example, some <br>
allow you to write "protocol plugins" that will decode any protocol (such aas a custom protocol that you've developed). <br>
<br>
The disadvantages of sniffers are several. First, software critics call a ssniffer "inexpensive" when it costs less than $2000, <br>
and they positively gush when they cost less than $1000. (This is because tthe original sniffers were very expensive pieces <br>
of dedicated hardware; the Sniffer hardware analyzer from Network General ccosts about $15,000, for example.) There <br>
are a few truly inexpensive ones, but they all have serious limitations: soome just dump the data raw to disk, others run <br>
only under uncommon operating systems like DOS and UNIX, and still others aare just plain weak. Another problem with <br>
sniffers is that the packets must travel over a LAN before they can capturee them -- many sniffers won't work on a <br>
machine connected through PPP. <br>
<br>
All that aside, however, sometimes a sniffer is the only way to find out whhat you want to know about your program's <br>
behavior. If you've got the cash, a good sniffer is almost always the best tool for the job. <br>
<br>
<br>
The third method is something I call a "Winsock shim." A shim sits between your program and Winsock, either by <br>
replacing the DLL itself with a proxy DLL, or by "hooking" the Winsock DLL''s API. These tools are limited to <br>
monitoring events on the Winsock layer itself, and can only monitor a singlle network conversation. Their advantages are <br>
that this is usually sufficient, and that the most expensive shims cost lesss than $200. <br>
<br>
The Resources page has links to several good sniffers and shims. <br>
<br>
2.10 - How do I get a readable error message from a Winsock error number? <br>
<br>
There are a number of ways, but keep in mind that you are best off creatingg your own error messages. Only you can <br>
decide on proper error messages, because some error values occur in a greatt variety of situations. For example, <br>
WSAEFAULT could mean "bad pointer passed," or "passed buffer too small," orr even "That version of the API is not <br>
supported." The Winsock spec does document the most likely error values thaat a given API will return, which you can <br>
use in constructing your error handlers. <br>
<br>
Still, sometimes an API call returns something unexpected, so a cryptic errror message is better than none at all. In that <br>
case, you can use one of the two following methods: an RC file for Winsock 1.1 messages, or the FormatMessage API <br>
in Win32. (I have not successfully used FormatMessage for this, but some saay it works. Caveat hacker.) <br>
<br>
2.11 - Winsock keeps returning the error WSAEWOULDBLOCK. What's wrong with my <br>
program? <br>
<br>
<br>
Not a thing. WSAEWOULDBLOCK is a perfectly normal occurrence in programs ussing non-blocking and <br>
asynchronous sockets. It's Winsock's way of telling your program "I can't ddo that right now, because I would have to <br>
block to do so." <br>
<br>
The next question is, how do you know when it's safe to try again? In the ccase of asynchronous sockets, Winsock will <br>
send you an FD_WRITE message after a failed send() call when it is safe to write; it will send you an FD_READ <br>
message when it is safe to read after a failed recv() call. Similarly, in aa non-blocking sockets program that uses <br>
select(), the "writefds" will be set when it's okay to write, and the "readdfds" will be set if there is data to read. <br>
<br>
2.12 - Winsock keeps corrupting my data; I thought TCP was supposed to be reliabble! <br>
<br>
This problem is sometimes voiced, "My client program sent 100 bytes, but thhe server program only got 50. What gives?" <br>
Both these questions indicate a misunderstanding of how TCP works. (I'm nott disparaging anyone here -- I had these <br>
misconceptions once, too. I think this issue is one of TCP/IP's rites of paassage.) <br>
<br>
The critical issue is that TCP is a stream protocol. This means that if youu send 100 bytes, the receiving end could receive <br>
all 100 bytes at once, or 100 separate 1-byte chunks, or four 25-byte chunkks. Or, the receiver could even receive that <br>
100 byte block plus some data from the previous send and some from the succceeding send. Re-read this paragraph until <br>
you truly understand it. I'm not kidding. <br>
<br>
"Okay, so now that I understand stream protocols, what do I do if I want thhe receiving end to read whole packets only?" <br>
you ask. The two most common ways are to either prefix the packet with a leength value, or terminate it with something <br>
unique. (For what it's worth, a prefix is most helpful if it is a binary-enncoded number; see Question 2.13 for more on this <br>
subject.) For example, you could create your protocol such that every packeet is preceded by a 2-byte short integer that <br>
tells how long the packet is. An example of the other method would be a CRLLF (carriage return, line feed) as used in the <br>
NNTP, POP3, SMTP and HTTP protocols. I prefer the former method, because thhe latter requires your program to <br>
blindly read until it finds the end of the packet, whereas the former lets the program start dealing with the packet just as <br>
soon as the length prefix comes in. <br>
<br>
In any case, the most important thing is to check the return value of recv((), which indicates how many bytes it placed in <br>
your buffer. Between this and your new packet-finding code, you should be aable to reliably read complete packets from <br>
the TCP stream. <br>
<br>
2.13 - I've read Question 2.12, and that's not the problem. Have any more brightt ideas? <br>
<br>
Another possible problem, if your program is talking to one on another plattform, is the byte order of integers. You have <br>
probably noticed all that ntohs() and htonl() stuff required in Winsock proogramming, but you might not know why <br>
it's required. The reason is that there are two major ways of storing integgers on a computer: big-endian and little-endian. <br>
Big-endian numbers are stored with the most significant byte in the lowest memory location ("big-end first"), whereas <br>
little-endian systems reverse this. (There are even bizarre "middle-endian"" systems!) Obviously two computers must <br>
agree on a common number format if they are to communicate, so TCP/IP speciifies that the headers use "network byte <br>
order." <br>
<br>
The end result is, if you are sending bare integers as part of your networkk protocol, and the receiving end is on a platform <br>
The end result is, if you are sending bare integers as part of your networkk protocol, and the receiving end is on a platform <br>
that uses a different integer representation, it will perceive the data as garbled. To fix this, follow the lead of the TCP <br>
protocol and use network byte order, always. <br>
<br>
For what it's worth, network byte order is big-endian, though you should neever take advantage of this fact. Some <br>
programmers working on big-endian machines ignore byte ordering issues, butt this is bad style, if for no other reason than <br>
because it creates bad habits that can bite you later. <br>
<br>
Other interesting trivia: the most common little-endian machines are the Inntel x86 and the Digital Alpha; most everything <br>
else, including the Motorola 680x0, the Sun SPARC and the MIPS Rx000, are bbig-endian. Oddly enough, there are a <br>
few "bi-endian" devices that can operate in either mode, like the PowerPC aand the HP PA-RISC 8000. Most <br>
PowerPCs always run in big-endian mode, however, and I suspect that the samme is true of the PA-RISC. <br>
<br>
v-- <br>
人生在世,如果不能喝酒,不能想女人,连人家欺负到了头上也不能还手,还不如死了算了了 <br>
<br>
※ 来源:·BBS 水木清华站 bbs.net.tsinghua.edu.cn·[FROM: 166.111.74.189] <br>
发信人: Christopher (Chris), 信区: Winsock <br>
标 题: Re: 一个不错的Winsocket站点 <br>
发信站: BBS 水木清华站 (Fri Feb 27 10:12:17 1998) <br>
<br>
【 在 Christopher (Chris) 的大作中提到: 】 <br>
第三部分,建议用WWW浏览。 <br>
Section 3 - Advanced Issues <br>
<br>
3.1 - How can I open a raw data socket? <br>
<br>
Under Winsock 1.1, the SOCK_RAW socket type is optional. Many major Winsockk vendors implement it, but <br>
Microsoft's stacks do not. <br>
<br>
SOCK_RAW was not mandated in Winsock 1.1 because: 1) not every stack vendorr can supply a complete <br>
SOCK_RAW interface, and 2) the Winsock spec's writers decided not to mess wwith the problem of how "raw" a <br>
SOCK_RAW connection should be. Since the spec does not enlighten us as to wwhat we should expect from a <br>
SOCK_RAW implementation, it is hard to give examples of "proper" use. <br>
<br>
The Winsock 2 spec gives more details about raw sockets, and Microsoft's Wiinsock 2 stacks do implement some types <br>
of raw sockets. Unfortunately, this support is fairly sparse. So far as I ccan tell, Microsoft only supports raw IGMP and <br>
ICMP sockets, the latter so that programs can send "ping" packets. (See thee raw sockets ping example for an program <br>
that uses this functionality.) Microsoft stacks do not support raw IP or "ppacket capturing" from the Winsock layer, <br>
supposedly so people can't write IP spoofing programs and packet sniffers. This is somewhat understandable given that <br>
Windows 95 has essentially no security, so you couldn't do things like lockk out raw sockets for unprivlegded users. (See <br>
Questions 3.13 and 3.14 for more information.) <br>
<br>
Other Winsocks may provide more raw sockets capabilities, but keep in mind that using this support might tie your <br>
program to their particular Winsock implementation. <br>
<br>
3.2 - How can I "ping" another machine with Winsock? <br>
<br>
The "official" method uses the IPPROTO_ICMP raw socket type defined by Winssock 2. I have tested this method <br>
under Windows NT 4.0, and it works well. Reports indicate that it works undder Windows 95 with the Winsock 2 SDK <br>
as well. Note that this code might actually work under some non-Microsoft WWinsock 1.1 stacks, but I have heard no <br>
such reports. [C++ example] <br>
<br>
The other method uses ICMP.DLL, which is an extension specific to Microsoftt stacks. While it does currently work, <br>
Microsoft discourages its use in the strongest terms possible, claiming thaat the API will disappear as soon as a better <br>
method exists. (I am guessing that this refers to the deployment of Windowss 98, which will have Winsock 2's raw <br>
sockets support.) Its main advantage is that it works under Winsock 1.1, whhile the above method generally does not. <br>
[C++ example] <br>
<br>
I want to point out that if your program needs to ping another machine, it can simply be the result of a poorly-designed <br>
protocol, rather than an actual need. Granted, it can be used to provide moore effective feedback in your program, but <br>
you shouldn't rely on it for issues like connection checking. For example, I'm always seeing people ask about pinging <br>
when what they really want is to use asynchronous sockets, so they can moniitor the FD_CLOSE event. (See Tutorial 1 <br>
for more ranting about blocking sockets and such.) <br>
<br>
3.3 - How do I share a socket between two processes? <br>
<br>
<br>
This is not possible under Winsock 1.1, because it wasn't considered sufficciently important at the time the spec was <br>
created. <br>
<br>
Winsock 2, however, does provide support for this through the WSADuplicateSSocket() facility. The spec describes <br>
this method in more detail. Another interesting source of information aboutt this is Microsoft Knowledge Base article <br>
Q150523, which describes the difference between socket inheritance between Windows 95 and Windows NT. <br>
<br>
3.4 - Why is ioctlsocket() so crippled compared to UNIX ioctl()? <br>
<br>
Probably for portability reasons. Keep in mind that Winsock was an after-thhe-fact specification when it was first created; <br>
that is, it tried to provide a BSD sockets-like interface for common Windowws network stacks. So, many of the familiar <br>
SIOC* and FIO* parameters were left out because there was no simple way to implement them on the existing stacks. <br>
Also, unlike Winsock's ioctlsocket(), BSD's ioctl() call controls more thann socket descriptors. <br>
<br>
There are two possible ways to get more functionality. The first is vendor support. Some Winsock vendors may provide <br>
support for the more advanced ioctl() parameters. (This is less likely in ttoday's Microsoft-dominated Winsock world <br>
than it was in the past, when Microsoft's Winsock offerings were either nonnexistent or weak.) The other is Winsock 2, <br>
which offers a number of new options. The new options mainly center around new Winsock 2 features like Quality of <br>
Service and Multicasting, but a few new general-use items have been added, like getting information about the <br>
computer's network interfaces. Also, since file and socket descriptors are equivalent under Winsock 2, the Win32 API <br>
might actually provide the behavior you want among its I/O APIs. <br>
<br>
<br>
3.5 - How can I get the local user name? <br>
<br>
There are a few ways. The easiest is to use the Win32 call GetUserName(). [[C++ Example]. <br>
<br>
The other way is shown in the Microsoft Knowledge Base article Q155698 ("Hoow To Look Up Current User Name <br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -