Using sockets in windows

Windows Sockets 2

Purpose

Windows Sockets 2 (Winsock) enables programmers to create advanced Internet, intranet, and other network-capable applications to transmit application data across the wire, independent of the network protocol being used. With Winsock, programmers are provided access to advanced MicrosoftВ® WindowsВ® networking capabilities such as multicast and Quality of Service (QoS).

Winsock follows the Windows Open System Architecture (WOSA) model; it defines a standard service provider interface (SPI) between the application programming interface (API), with its exported functions and the protocol stacks. It uses the sockets paradigm that was first popularized by Berkeley Software Distribution (BSD) UNIX. It was later adapted for Windows in Windows Sockets 1.1, with which Windows Sockets 2 applications are backward compatible. Winsock programming previously centered around TCP/IP. Some programming practices that worked with TCP/IP do not work with every protocol. As a result, the Windows Sockets 2 API adds functions where necessary to handle several protocols.

Developer audience

Windows Sockets 2 is designed for use by C/C++ programmers. Familiarity with Windows networking is required.

Run-time requirements

Windows Sockets 2 can be used on all Windows platforms. Where certain implementations or capabilities of Windows Sockets 2 platform restrictions do exist, they are clearly noted in the documentation.

Getting Started with Winsock

The following is a step-by-step guide to getting started with Windows Sockets programming. It is designed to provide an understanding of basic Winsock functions and data structures, and how they work together.

The client and server application that is used for illustration is a very basic client and server. More advanced code examples are included in the samples included with the Microsoft Windows Software Development Kit (SDK).

The first few steps are the same for both client and server applications.

The following sections describe the remaining steps for creating a Winsock client application.

The following sections describe the remaining steps for creating a Winsock server application.

The complete source code for these basic examples.

Advanced Winsock Samples

Several more advanced Winsock client and server samples are included with the Windows SDK. By default, the Winsock sample source code is installed in the following directory by the Windows SDK for WindowsВ 7:

C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\NetDs\winsock

On earlier versions of the Windows SDK, the version number in the above path would change. For example, the Winsock sample source code is installed in the following default directory by the Windows SDK for WindowsВ Vista

C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\NetDs\winsock

The more advanced samples listed below in order from higher to lower performance are found in the following directories:

This directory contains three sample programs that use I/O completion ports. The programs include a Winsock server (iocpserver) that uses the WSAAccept function, a Winsock server (iocpserverex) that uses the AcceptEx function, and a simple multithreaded Winsock client (iocpclient) used to test either of these servers. The server programs support multiple clients connecting via TCP/IP and sending arbitrary sized data buffers which the server then echoes back to the client. For convenience, a simple client program, iocpclient, was developed to connect and continually send data to the server to stress it using multiple threads. Winsock servers that use I/O completion ports provide the most performance capability.

This directory contains a sample server program that uses overlapped I/O. The sample program uses the AcceptEx function and overlapped I/O to handle multiple asynchronous connection requests from clients effectively. The server uses the AcceptEx function to multiplex different client connections in a single-threaded Win32 application. Using overlapped I/O allows for greater scalability.

Читайте также:  Как изменить папку проводника windows 10

This directory contains a basic sample program that demonstrates the use of the WSAPoll function. The combined client and server program are non-blocking and use the WSAPoll function to determine when it is possible to send or receive without blocking. This sample is more for illustration and is not a high-performance server.

This directory contains three basic sample programs that demonstrate the use of multiple threads by a server. The programs include a simple TCP/UDP server (simples), a TCP-only server (simples_ioctl) that uses the select function in a Win32 console application to support multiple client requests, and a client TCP/UDP program (simplec) for testing the servers. The servers demonstrates the use of multiple threads to handle multiple client requests. This method has scalability issues since a separate thread is created for each client request.

This directory contains a basic sample server and client program. The server demonstrates the use of either non-blocking accept using the select function or asynchronous accept using the WSAAsyncSelect function. This sample is more for illustration and is not a high-performance server.

Sockets

Sockets are a low-level data transfer technology on top of which many networking protocols are implemented. UWP offers TCP and UDP socket classes for client-server or peer-to-peer applications, whether connections are long-lived or an established connection is not required.

This topic focuses on how to use the Universal Windows Platform (UWP) socket classes that are in the Windows.Networking.Sockets namespace. But you can also use Windows Sockets 2 (Winsock) in a UWP app.

As a consequence of network isolation, Windows disallows establishing a socket connection (Sockets or WinSock) between two UWP apps running on the same machine; whether that’s via the local loopback address (127.0.0.0), or by explicitly specifying the local IP address. For details about mechanisms by which UWP apps can communicate with one another, see App-to-app communication.

Build a basic TCP socket client and server

A TCP (Transmission Control Protocol) socket provides low-level network data transfers in either direction for connections that are long-lived. TCP sockets are the underlying feature used by most of the network protocols used on the Internet. To demonstrate basic TCP operations, the example code below shows a StreamSocket and a StreamSocketListener sending and receiving data over TCP to form an echo client and server.

To begin with as few moving parts as possible—and to sidestep network isolation issues for the present—create a new project, and put both the client and the server code below into the same project.

You’ll need to declare an app capability in your project. Open your app package manifest source file (the Package.appxmanifest file) and, on the Capabilities tab, check Private Networks (Client & Server). This is how that looks in the Package.appxmanifest markup.

Instead of privateNetworkClientServer , you can declare internetClientServer if you’re connecting over the internet. Both StreamSocket and StreamSocketListener need one or other of these app capabilities to be declared.

An echo client and server, using TCP sockets

Construct a StreamSocketListener and begin listening for incoming TCP connections. The StreamSocketListener.ConnectionReceived event is raised each time a client establishes a connection with the StreamSocketListener.

Also construct a StreamSocket, establish a connection to the server, send a request, and receive a response.

Create a new Page named StreamSocketAndListenerPage . Put the XAML markup in StreamSocketAndListenerPage.xaml , and the put the imperative code inside the StreamSocketAndListenerPage class.

References to StreamSockets in C++ PPL continuations (applies to C++/CX, primarily)

If you use C++/WinRT coroutines, and you pass parameters by value, then this issue doesn’t apply. For parameter-passing recommendations, see Concurrency and asynchronous operations with C++/WinRT.

A StreamSocket remains alive as long as there’s an active read/write on its input/output stream (let’s take for example the StreamSocketListenerConnectionReceivedEventArgs.Socket that you have access to in your StreamSocketListener.ConnectionReceived event handler). When you call DataReader.LoadAsync (or ReadAsync/WriteAsync/StoreAsync ), then that holds a reference to the socket (via the socket’s input stream) until the Completed event handler (if any) of the LoadAsync is done executing.

Читайте также:  Windows 10 отключить экран добро пожаловать

The Parallel Patterns Library (PPL) doesn’t schedule task continuations inline by default. In other words, adding a continuation task (with task::then() ) doesn’t guarantee that the continuation task will execute inline as the completion handler.

From the perspective of the StreamSocket, the completion handler is done executing (and the socket is eligible for disposal) before the continuation body runs. So, to keep your socket from being disposed if you want to use it inside that continuation, you need to either reference the socket directly (via lambda capture) and use it, or indirectly (by continuing to access args->Socket inside continuations), or force continuation tasks to be inline. You can see the first technique (lambda capture) in action in the StreamSocket sample. The C++/CX code in the Build a basic TCP socket client and server section above uses the second technique—it echoes the request back as a response, and it accesses args->Socket from within one of the innermost continuations.

The third technique is appropriate when you’re not echoing a response back. You use the task_continuation_context::use_synchronous_execution() option to force PPL to execute the continuation body inline. Here’s a code example showing how to do it.

This behavior applies to all of the sockets and WebSockets classes in the Windows.Networking.Sockets namespace. But client-side scenarios usually store sockets in member variables, so the issue is most applicable to the StreamSocketListener.ConnectionReceived scenario, as illustrated above.

Build a basic UDP socket client and server

A UDP (User Datagram Protocol) socket is similar to a TCP socket in that it also provides low-level network data transfers in either direction. But, while a TCP socket is for long-lived connections, a UDP socket is for applications where an established connection is not required. Because UDP sockets don’t maintain connection on both endpoints, they’re a fast and simple solution for networking between remote machines. But UDP sockets don’t ensure integrity of the network packets nor even whether packets make it to the remote destination at all. So your app will need to be designed to tolerate that. Some examples of applications that use UDP sockets are local network discovery, and local chat clients.

To demonstrate basic UDP operations, the example code below shows the DatagramSocket class being used to both send and receive data over UDP to form an echo client and server. Create a new project, and put both the client and the server code below into the same project. Just as for a TCP socket, you’ll need to declare the Private Networks (Client & Server) app capability.

An echo client and server, using UDP sockets

Construct a DatagramSocket to play the role of the echo server, bind it to a specific port number, listen for an incoming UDP message, and echo it back. The DatagramSocket.MessageReceived event is raised when a message is receieved on the socket.

Construct another DatagramSocket to play the role of the echo client, bind it to a specific port number, send a UDP message, and receive a response.

Create a new Page named DatagramSocketPage . Put the XAML markup in DatagramSocketPage.xaml , and the put the imperative code inside the DatagramSocketPage class.

Background operations and the socket broker

You can use the socket broker, and control channel triggers, to ensure that your app properly receives connections or data on sockets while it’s not in the foreground. For more info, see Network communications in the background.

Batched sends

Whenever you write to the stream associated with a socket, a transition happens from user mode (your code) to kernel mode (where the network stack is). If you’re writing many buffers at a time then these repeated transitions compound into substantial overhead. Batching your sends is a way to send multiple buffers of data together, and avoid that overhead. It’s especially useful if your app is doing VoIP, VPN, or other tasks that involve moving a lot of data as efficiently as possible.

Читайте также:  Hdd scan mac os

This section demonstrates a couple of batched sends techniques that you can use with a StreamSocket or a connected DatagramSocket.

To get a baseline, let’s see how to send a large number of buffers in an inefficient way. Here’s a minimal demo, using a StreamSocket.

This first example of a more efficient technique is only appropriate if you’re using C#. Change OnNavigatedTo to call BatchedSendsCSharpOnly instead of SendMultipleBuffersInefficiently or SendMultipleBuffersInefficientlyAsync .

This next example is appropriate for any UWP language, not just for C#. It relies on the behavior in StreamSocket.OutputStream and DatagramSocket.OutputStream that batches sends together. The technique calls FlushAsync on that output stream which, as of WindowsВ 10, is guaranteed to return only after all operations on the output stream have completed.

There are some important limitations imposed by using batched sends in your code.

  • You cannot modify the contents of the IBuffer instances being written until the asynchronous write is complete.
  • The FlushAsync pattern only works on StreamSocket.OutputStream and DatagramSocket.OutputStream.
  • The FlushAsync pattern only works in WindowsВ 10 and onward.
  • In other cases, use Task.WaitAll instead of the FlushAsync pattern.

Port sharing for DatagramSocket

You can configure a DatagramSocket to coexist with other Win32 or UWP multicast sockets bound to the same address/port. You do this by setting the DatagramSocketControl.MulticastOnly to true before binding or connecting the socket. You access an instance of DatagramSocketControl from the DatagramSocket object itself via its DatagramSocket.Control property.

Providing a client certificate with the StreamSocket class

StreamSocket supports using SSL/TLS to authenticate the server that the client app is talking to. In some cases, the client app needs to authenticate itself to the server using an SSL/TLS client certificate. You can provide a client certificate with the StreamSocketControl.ClientCertificate property before binding or connecting the socket (it must be set before the SSL/TLS handshake is started). You access an instance of StreamSocketControl from the StreamSocket object itself via its StreamSocket.Control property. If the server requests the client certificate then Windows will respond with the client certificate that you provided.

As indicated by the comment in the code examples below, your project needs to declare the sharedUserCertificates app capability for this code to work.

Handling exceptions

An error encountered on a DatagramSocket, StreamSocket, or StreamSocketListener operation is returned as an HRESULT value. You can pass that HRESULT value to the SocketError.GetStatus method to convert it into a SocketErrorStatus enumeration value.

Most SocketErrorStatus enumeration values correspond to an error returned by the native Windows sockets operation. Your app can switch on SocketErrorStatus enumeration values to modify app behavior depending on the cause of the exception.

For parameter validation errors, you can use the HRESULT from the exception to learn more detailed information about the error. Possible HRESULT values are listed in Winerror.h , which can be found in your SDK installation (for example, in the folder C:\Program Files (x86)\Windows Kits\10\Include\ \shared ). For most parameter validation errors, the HRESULT returned is E_INVALIDARG.

The HostName constructor can throw an exception if the string passed is not a valid host name. For example, it contains characters that are not allowed, which is likely if the host name is typed in to your app by the user. Construct a HostName inside a try/catch block. That way, if an exception is thrown, the app can notify the user and request a new host name.

Оцените статью