Sie sind auf Seite 1von 12

Network Programming

BTCS703
Winsock programming

Winsock is a programming interface and the supporting program that handles


input/output requests for Internet applications in a Windows operating system. It's called
Winsock because it's an adaptation for Windows of the Berkeley UNIX sockets
interface.Sockets is a particular convention for connecting with and exchanging data between
two program processes within the same computer or across a network.

Winsock runs between an application program such as a Netscape browser and the Internet
program in your computer that uses TCP/IP. A request flows in the following order:
Web browser or other application
|
winsock.dll
|
TCP/IP layers
|
Modem or network card
|
The Internet and destination
Winsock provides this interface for different versions of the Windows operating system. A
comparable interface exists for Mac computers. Beginning with Windows 95, Winsock came
as part of the operating system, but in earlier systems, a Winsock program had to be installed.
UNIX systems do not require a Winsock equivalent because TCP/IP and its use of sockets
was designed to run directly with UNIX application programs.

A number of companies offer a Winsock program, sometimes along with a suite of Internet
protocol programs and applications. For example, Chameleon offers a suite that includes a
Web browser, an FTP utility, a mail utility, and others. The Winsock program is included.
The Trumpet Winsock is another popular stand-alone version. Winsock runs as a Windows
dynamic link library (DLL) file. That is, it is loaded into the computer when an application
needs it but doesn't need to be included as part of the application.
Windows socket API

What is Windows Sockets


The Windows Sockets specification defines a network programming interface for Microsoft
Windows which is based on the "socket" paradigm popularized in the Berkeley Software
Distribution (BSD) from the University of California at Berkeley. It encompasses both
familiar Berkeley socket style routines and a set of Windows-specific extensions designed to
allow the programmer to take advantage of the message-driven nature of Windows.
The Windows Sockets Specification is intended to provide a single API to which application
developers can program and multiple network software vendors can conform. Furthermore, in
the context of a particular version of Microsoft Windows, it defines a binary interface (ABI)
such that an application written to the Windows Sockets API can work with a conformant
protocol implementation from any network software vendor. This specification thus defines
the library calls and associated semantics to which an application developer can program and
which a network software vendor can implement.
Network software which conforms to this Windows Sockets specification will be considered
"Windows Sockets Compliant". Suppliers of interfaces which are "Windows Sockets
Compliant" shall be referred to as "Windows Sockets Suppliers". To be Windows Sockets
Compliant, a vendor must implement 100% of this Windows Sockets specification.
Applications which are capable of operating with any "Windows Sockets Compliant"
protocol implementation will be considered as having a "Windows Sockets Interface" and
will be referred to as "Windows Sockets Applications".
This version of the Windows Sockets specification defines and documents the use of the API
in conjunction with the Internet Protocol Suite (IPS, generally referred to as TCP/IP).
Specifically, all Windows Sockets implementations support both stream (TCP) and datagram
(UDP) sockets.
While the use of this API with alternative protocol stacks is not precluded (and is expected to
be the subject of future revisions of the specification), such usage is beyond the scope of this
version of the specification.
Winsock API

Winsock is an API that allows Windows-based applications to access the transport protocols.
Winsock in Windows 2000 is a protocol-independent networking API. Winsock is the
Windows 2000 implementation of the widely-used Sockets API, the standard for accessing
datagram and session services over TCP/IP, NWLink IPX/SPX NetBIOS, and AppleTalk.
Applications written to the Winsock interface include File Transfer Protocol (FTP) and
Simple Network Management Protocol (SNMP). Winsock performs the following:
 Provides a familiar networking API for programmers using Windows or UNIX.
 Offers binary compatibility between the heterogeneous, Windows-based TCP/IP stack
and utility vendors.
 Supports both connection-oriented and connectionless protocols.
Windows 2000 includes Winsock 1.1 support. Winsock 2.0 extends the Winsock 1.1 interface
to provide access to networks using protocols other than TCP/IP, such as NetWare and
AppleTalk. Winsock 2.0 provides the following enhancements over Winsock 1.1:
 Name registration and resolution. 
Winsock 2.0 provides an interface that applications can use to access many different
namespaces, such as Domain Name System (DNS), Novell Directory Services (NDS), and
X.500.
 Support for real-time multimedia communications. 
Winsock supports several multimedia enhancements, including Quality of Service (QoS).
 Protocol-independent multipoint and multicast. 
Winsock 2.0 enables applications to take advantage of the multipoint and multicast
capabilities of transport stacks.
Winsock Architecture
Winsock 2.0 is a Windows Open Systems Architecture (WOSA)–compliant interface that
enables a front-end application and a back-end service to communicate. The Winsock 2.0
interface includes the following components:
 The Winsock 1.1 Application Programming Interface (API)
 The Winsock 2.0 Application Programming Interface (API)
 The Winsock 2.0 Transport Service Providers
 Layered Service Providers
Figure shows the Winsock 2.0 architecture.
Windows Sockets

The Windows Sockets 2 architecture is compliant with the Windows Open System
Architecture (WOSA), as illustrated below:

Winsock defines a standard service provider interface (SPI) between the application
programming interface (API), with its functions exported from WS2_32.dll and the protocol
stacks. Consequently, Winsock support is not limited to TCP/IP protocol stacks as is the case
for Windows Sockets 1.1.

With the Windows Sockets 2 architecture, it is not necessary or desirable, for stack vendors
to supply their own implementation of WS2_32.dll, since a single WS2_32.dll must work
across all stacks. The WS2_32.dll and compatibility shims should be viewed in the same way
as an operating system component.

Blocking I/O model

Some control over how the wait for I/O to complete is accommodated is available to the
programmer of user applications. Most I/O requests are considered blocking requests,
meaning that control does not return to the application until the I/O is complete. The delayed
from systems calls such read() and write() can be quite long. Using systems call that block is
sometimes call synchronous programming. In most cases, the wait is not really a problem
because the program can not do anything else until the I/O is finished. However, in cases
such as network programming with multiple clients or with graphical user interface
programming, the program may wish to perform other activity as it continues to wait for
more data or input from users.
One solution for these situations is to use multiple threads so that one part of the program is
not waiting for unrelated I/O to complete. Another alternative is to
use asynchronous programming techniques with nonblocking system calls. An
asynchronous call returns immediately, without waiting for the I/O to complete. The
completion of the I/O is later communicated to the application either through the setting of
some variable in the application or through the triggering of a signal or call-back routine that
is executed outside the linear control flow of the application.

Blocking I/O system calls (a) do not return until the I/O is complete. Nonblocking I/O sytems
calls return immediately. The process is later notified when the I/O is complete.

A good example of nonblocking behavior is the select() system cal for network sockets.


Using select(), an application can monitor several resources at the same time and can also
poll for network activity without blocking. The select() system call identifies if data is
pending or not, then read() or write() may be used knowing that they will complete
immediately.

  Correct asynchronous programming can be complex, but since asynchronous programs have
only one thread of execution, problems of Deadlock and Data Inconsistency are eliminated.
For this reason, several programming frameworks exist that handle the difficult I/O issues
making asynchronous programming much easier.

Asynchronous programming with call backs appears to be the most common approach for
graphical user interface programming. It also has some advocates in the network
programming realm, but multi-threaded programming is more often used with network
programming.

Blocking sockets
A socket is in blocking mode when an I/O call waits for an event to complete. If the blocking
mode is set for a socket, the calling program is suspended until the expected event completes.
If nonblocking is set by the FCNTL() or IOCTL() calls, the calling program continues even
though the I/O call might not have completed. If the I/O call could not be completed, it
returns with ERRNO EWOULDBLOCK. (The calling program should use SELECT() to test
for completion of any socket call returning an EWOULDBLOCK.)
Note: The default mode is blocking.
If data is not available to the socket, and the socket is in blocking and synchronous modes,
the READ call blocks the caller until data arrives.
All IBM® TCP/IP Services socket APIs support nonblocking socket calls. Some APIs, in
addition to nonblocking calls, support asynchronous socket calls.
Blocking
The default mode of socket calls is blocking. A blocking call does not return to your
program until the event you requested has been completed. For example, if you issue
a blocking recvfrom() call, the call does not return to your program until data is
available from the other socket application. A blocking accept() call does not return to
your program until a client connects to your socket program.
Nonblocking
Change a socket to nonblocking mode using the ioctl() call that specifies command
FIONBIO and a fullword (four byte) argument with a nonzero binary value. Any
succeeding socket calls against the involved socket descriptor are nonblocking calls.
Alternatively, use the fcntl() call using the F_SETFL command and FNDELAY as an
argument.
Nonblocking calls return to your program immediately to reveal whether the
requested service was completed. An error number may mean that your call would
have blocked had it been a blocking call.
If the call was, for example, a recv() call, your program might have implemented its
own wait logic and reissued the nonblocking recv() call at a later time. By using this
technique, your program might have implemented its own timeout rules and closed
the socket, failing receipt of data from the partner program, within an application-
determined period of time.
A new ioctl() call can be used to change the socket from nonblocking to blocking
mode using command FIONBIO and a fullword argument of value 0 (F'0').
Asynchronous
Like nonblocking calls, asynchronous calls return control to your program
immediately. But in this case, there is no need to reissue the call. Asynchronous calls
are available with the macro API. For more information, see Task management and
asynchronous function processing.
Table 1 lists the actions taken by the socket programming interface.
Table 1. Socket programming interface actions

Call type Socket state blocking Nonblocking

Types of read() Input is available Immediate return Immediate return


calls
No input is available Wait for input Immediate return with
EWOULDBLOCK error
number (select() exception:
READ)

Types of write() Output buffers Immediate return Immediate return


calls available

No output buffers Wait for output Immediate return with


available buffers EWOULDBLOCK error
number (select() exception:
WRITE)

accept() call New connection Immediate return Immediate return

No connections Wait for new Immediate return with


queued connection EWOULDBLOCK error
number (select() exception:
READ)

connect() call   Wait Immediate return with


EINPROGRESS error number
(select() exception: WRITE)

Test pending activity on a number of sockets in a synchronous program by using the select()
call. Pass the list of socket descriptors that you want to test for activity to the select() call;
specify by socket descriptor the following type of activity you want test to find:
 Pending data to read
 Ready for new write
 Any exception condition
When you use select() call logic, you do not issue any socket call on a given socket until the
select() call tells you that something has happened on that socket; for example, data has
arrived and is ready to be read by a read() call. By using the select() call, you do not issue a
blocking call until you know that the call cannot block.
The select() call can itself be blocking, nonblocking, or, for the macro API, asynchronous. If
the call is blocking and none of the socket descriptors included in the list passed to the
select() call have had any activity, the call does not return to your program until one of them
has activity, or until the timer value passed on the select() call expires.
The select() call and selectex() call are available. The difference between select() and
selectex() calls is that selectex() call allows you to include nonsocket related events in the list
of events that can trigger the selectex() call to complete. You do so by passing one or more
MVS™ event control blocks (ECBs) on the selectex() call. If there is activity on any of the
sockets included in the select list, if the specified timer expires, or if one of the external
events completes, the selectex() call returns to your program.
Typically, a server program waits for socket activity or an operator command to shut it down.
By using the selectex() call, a shutdown ECB can be included in the list of events to be
monitored for activity.

Timeouts for blocking I/O

Many programmers dread the thought of handling network timeouts. A common fear is that a
simple, single-threaded network client without timeout support will balloon into a complex
multithreaded nightmare, with separate threads needed to detect network timeouts, and some
form of notification process at work between the blocked thread and the main application.
While this is one option for developers, it is not the only one. Dealing with network timeouts
need not be a difficult task, and in many cases you can completely avoid writing code for
additional threads.

When working with network connections, or any type of I/O device, there are two
classifications of operations:

 Blocking operations: Read or write stalls, operation waits until I/O device is ready
 Nonblocking operations: Read or write attempt is made, operation aborts if I/O
device is not ready

Java networking is, by default, a form of blocking I/O. Thus, when a Java networking
application reads from a socket connection, it will generally wait indefinitely if there is no
immediate response. If no data is available, the program will keep waiting, and no further
work can be done. One solution, which solves the problem but introduces a little extra
complexity, is to have a second thread perform the operation; this way, if the second thread
becomes blocked the application can still respond to user commands, or even terminate the
stalled thread if necessary.
This solution is often employed, but there is a much simpler alternative. Java also supports
nonblocking network I/O, which can be activated on any Socket,ServerSocket,
or DatagramSocket. It is possible to specify the maximum length of time that a read or write
operation will stall before returning control back to the application. For network clients, this
is the easiest solution and offers simpler, more manageable code.
The only drawback to nonblocking network I/O under Java is that it requires an existing
socket. Thus, while this method is perfect for normal read or write operations, a connect
operation can stall for a much longer period, since there is no method for specifying a timeout
period for connect operations. Many applications require this ability; you can, however,
easily avoid the extra work of writing additional code. I've written a small class that allows
you to specify a timeout value for a connection. It uses a second thread, but the internal
details are abstracted away. This approach works well, as it provides a nonblocking I/O
interface, and the details of the second thread are hidden from view.
Nonblocking network I/O

The simplest way of doing something often turns out to be the best way. While it is
sometimes necessary to use threads and blocking I/O, in the majority of cases nonblocking
I/O lends itself to a far clearer and more elegant solution. With only a few lines of code, you
can incorporate timeout supports for any socket application. Don't believe me? Read on.
When Java 1.1 was released, it included API changes to the java.net package that allowed
programmers to specify socket options. These options give programmers greater control over
socket communication. One option in particular, SO_TIMEOUT, is extremely useful,
because it allows programmers to specify the amount of time that a read operation will block.
We can specify a short delay, or none at all, and make our networking code nonblocking.
Let's take a look at how this works. A new method, setSoTimeout ( int ) has been added to
the following socket classes:

 java.net.Socket
 java.net.DatagramSocket
 java.net.ServerSocket

This method allows us to specify a maximum timeout length, in milliseconds, that the
following network operations will block:

 ServerSocket.accept()
 SocketInputStream.read()
 DatagramSocket.receive()

Whenever one of these methods is called, the clock starts ticking. If the operation is not
blocked, it will reset and only restart once one of these methods is called again; as a result, no
timeout can ever occur unless you perform a network I/O operation. The following example
shows just how easy it can be to handle timeouts, without resorting to multiple threads of
execution:

// Create a datagram socket on port 2000 to listen for incoming UDP packets DatagramSocket
dgramSocket = new DatagramSocket ( 2000 );

// Disable blocking I/O operations, by specifying a five second timeout


dgramSocket.setSoTimeout ( 5000 );

Assigning a timeout value prevents our network operations from blocking indefinitely. At
this point, you're probably wondering what will happen when a network operation times out.
Rather than returning an error code, which might not always be checked by developers,
a java.io.InterruptedIOException is thrown. Exception handling is an excellent way of
dealing with error conditions, and allows us to separate our normal code from our error-
handling code. Besides, who religiously checks every return value for a null reference? By
throwing an exception, developers are forced to provide a catch handler for timeouts.
The following code snippet shows how to handle a timeout operation when reading from a
TCP socket:
// Set the socket timeout for ten seconds

connection.setSoTimeout (10000);

try

// Create a DataInputStream for reading from socket

DataInputStream din = new DataInputStream (connection.getInputStream());

// Read data until end of data

for (;;)

String line = din.readLine();

if (line != null)

System.out.println (line);

else

break;

// Exception thrown when network timeout occurs

catch (InterruptedIOException iioe)

System.err.println ("Remote host timed out during read operation");


}

// Exception thrown when general network I/O error occurs

catch (IOException ioe)

System.err.println ("Network I/O error - " + ioe);

With only a few extra lines of code for a try {} catch block, it's extremely easy to catch
network timeouts. An application can then respond to the situation without stalling itself. For
example, it could start by notifying the user, or by attempting to establish a new connection.
When using datagram sockets, which send packets of information without guaranteeing
delivery, an application could respond to a network timeout by resending a packet that had
been lost in transit. Implementing this timeout support takes very little time and leads to a
very clean solution. Indeed, the only time that nonblocking I/O is not the optimal solution is
when you also need to detect timeouts on connect operations, or when your target
environment does not support Java 1.1.

Timeout handling on connect operations

If your goal is to achieve complete timeout detection and handling, then you'll need to
consider connect operations. When creating an instance of java.net.Socket, an attempt to
establish a connection is made. If the host machine is active, but no service is running on the
port that is specified in thejava.net. Socket constructor, a ConnectionException will be
thrown and control will return to the application. However, if the machine is down, or if there
is no route to that host, the socket connection will eventually time out on its own much later.
In the meantime, your application remains frozen, and there is no way to change the timeout
value.
Though the socket constructor call will eventually return, it introduces a significant delay.
One way of dealing with this problem is to employ a second thread, which will perform the
potentially blocking connect, and to continually poll that thread to see if a connection has
been established.
This does not, however, always lead to an elegant solution. Yes, you could convert your
network clients into multithreaded applications, but often the amount of extra work required
to do this is prohibitive. It makes the code more complex, and when writing only a simple
network application, the amount of effort required is difficult to justify. If you write a lot of
network applications, you'd find yourself reinventing the wheel frequently. There is,
however, a simpler solution.
I've written a simple, reusable class that you can use in your own applications. The class generates a
TCP socket connection without stalling for long time periods. You simply call a getSocket method,
specifying the hostname, port, and timeout delay, and receive a socket. The following example shows
a connection request:

// Connect to a remote server by hostname, with a four second timeout

Socket connection = TimedSocket.getSocket("server.my-network.net", 23,


4000);

If all goes well, a socket will be returned, just like the standardjava.net.Socket constructors. If
the connection cannot be established before your specified timeout occurs, the method will
stop, and will throw anjava.io.InterruptedIOException, just as other socket-read operations
would when a timeout has been specified using a setSoTimeout method.

Das könnte Ihnen auch gefallen