OneWayUdpServerExample
Cet exemple montre un serveur UDP qui accepte un canal et reçoit des messages unidirectionnel.
OneWayUdpServer.cpp
//------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
//------------------------------------------------------------
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <stdio.h>
#include "WebServices.h"
#include "process.h"
#include "string.h"
#include "PurchaseOrder.wsdl.h"
// Print out rich error info
void PrintError(HRESULT errorCode, WS_ERROR* error)
{
wprintf(L"Failure: errorCode=0x%lx\n", errorCode);
if (errorCode == E_INVALIDARG || errorCode == WS_E_INVALID_OPERATION)
{
// Correct use of the APIs should never generate these errors
wprintf(L"The error was due to an invalid use of an API. This is likely due to a bug in the program.\n");
DebugBreak();
}
HRESULT hr = NOERROR;
if (error != NULL)
{
ULONG errorCount;
hr = WsGetErrorProperty(error, WS_ERROR_PROPERTY_STRING_COUNT, &errorCount, sizeof(errorCount));
if (FAILED(hr))
{
goto Exit;
}
for (ULONG i = 0; i < errorCount; i++)
{
WS_STRING string;
hr = WsGetErrorString(error, i, &string);
if (FAILED(hr))
{
goto Exit;
}
wprintf(L"%.*s\n", string.length, string.chars);
}
}
Exit:
if (FAILED(hr))
{
wprintf(L"Could not get error string (errorCode=0x%lx)\n", hr);
}
}
// Main entry point
int __cdecl wmain(int argc, __in_ecount(argc) wchar_t **argv)
{
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
HRESULT hr = NOERROR;
WS_ERROR* error = NULL;
WS_MESSAGE* message = NULL;
WS_CHANNEL* channel = NULL;
WS_LISTENER* listener = NULL;
WS_HEAP* heap = NULL;
HANDLE serverStartedEvent = NULL;
// Create an error object for storing rich error information
hr = WsCreateError(
NULL,
0,
&error);
if (FAILED(hr))
{
goto Exit;
}
// Create a heap to store deserialized data
hr = WsCreateHeap(
/*maxSize*/ 2048,
/*trimSize*/ 512,
NULL,
0,
&heap,
error);
if (FAILED(hr))
{
goto Exit;
}
// Create a listener
hr = WsCreateListener(
WS_CHANNEL_TYPE_DUPLEX,
WS_UDP_CHANNEL_BINDING,
NULL,
0,
NULL,
&listener,
error);
if (FAILED(hr))
{
goto Exit;
}
// Open listener at address
WS_STRING uri;
uri.chars = L"soap.udp://localhost:809";
uri.length = (ULONG)wcslen(uri.chars);
hr = WsOpenListener(
listener,
&uri,
NULL,
error);
if (FAILED(hr))
{
goto Exit;
}
hr = WsCreateChannelForListener(
listener,
NULL,
0,
&channel,
error);
if (FAILED(hr))
{
goto Exit;
}
hr = WsCreateMessageForChannel(
channel,
NULL,
0,
&message,
error);
if (FAILED(hr))
{
goto Exit;
}
// Create an event to synchronize the client and server processes.
serverStartedEvent = CreateEventW(
NULL,
TRUE,
FALSE,
L"WebServicesExampleServerStartedEvent");
if (NULL == serverStartedEvent)
{
wprintf(
L"Failed to create the client-server synchronization event (errorCode=0x%lx).\n",
GetLastError());
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}
// Server is started, set the event to signal the clients.
if (!SetEvent(
serverStartedEvent))
{
wprintf(
L"Failed to set the client-server synchronization event (errorCode=0x%lx).\n",
GetLastError());
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}
for (ULONG i = 0; i < 5; i++)
{
// Accept a channel from the client
hr = WsAcceptChannel(listener, channel, NULL, error);
if (FAILED(hr))
{
goto Exit;
}
// Set up the descriptions of the expected messages. In this case, we only expect purchase orders.
const WS_MESSAGE_DESCRIPTION* messageDescriptions[] = {&PurchaseOrder_wsdl.messages.PurchaseOrder};
// Receive the message and deserialize the element of the body into a _PurchaseOrderType structure.
// The values of the fields of the _PurchaseOrderType structure are allocated in the specified
// WS_HEAP, and are valid until WsResetHeap is called.
_PurchaseOrderType purchaseOrder;
hr = WsReceiveMessage(channel, message,
messageDescriptions, WsCountOf(messageDescriptions),
WS_RECEIVE_OPTIONAL_MESSAGE, WS_READ_REQUIRED_VALUE, heap,
&purchaseOrder, sizeof(purchaseOrder), NULL, NULL, error);
if (hr == WS_S_END)
{
// No more messages on channel
break;
}
if (FAILED(hr))
{
goto Exit;
}
// Print out purchase order contents
wprintf(L"%ld, %.*s\n",
purchaseOrder.quantity,
purchaseOrder.productName.length,
purchaseOrder.productName.chars);
// Reset the message so it can be used again
hr = WsResetMessage(
message,
error);
if (FAILED(hr))
{
goto Exit;
}
// Reset the heap, which will free any allocations made on it
hr = WsResetHeap(
heap,
error);
if (FAILED(hr))
{
goto Exit;
}
hr = WsCloseChannel(channel, NULL, error);
if (FAILED(hr))
{
goto Exit;
}
hr = WsResetChannel(channel, error);
if (FAILED(hr))
{
goto Exit;
}
}
Exit:
if (FAILED(hr))
{
// Print out the error
PrintError(hr, error);
}
fflush(
stdout);
if (channel != NULL)
{
// Close the channel
WsCloseChannel(channel, NULL, error);
}
if (channel != NULL)
{
WsFreeChannel(channel);
}
if (listener != NULL)
{
// Close the listener if it was opened
WsCloseListener(listener, NULL, error);
}
if (listener != NULL)
{
WsFreeListener(listener);
}
if (message != NULL)
{
WsFreeMessage(message);
}
if (NULL != serverStartedEvent)
{
CloseHandle(serverStartedEvent);
}
if (error != NULL)
{
WsFreeError(error);
}
if (heap != NULL)
{
WsFreeHeap(heap);
}
fflush(stdout);
return SUCCEEDED(hr) ? 0 : -1;
}
PurchaseOrder.wsdl
<wsdl:definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://example.org"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://example.org">
<wsdl:types>
<xsd:schema targetNamespace="http://example.org" elementFormDefault="qualified">
<xsd:element name="PurchaseOrderType">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="quantity" type="xsd:int"/>
<xsd:element minOccurs="0" name="productName" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="OrderConfirmationType">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="orderID" type="xsd:unsignedInt"/>
<xsd:element minOccurs="0" name="expectedShipDate" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetOrderStatusType">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="orderID" type="xsd:unsignedInt"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetOrderStatusResponseType">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="orderID" type="xsd:unsignedInt"/>
<xsd:element minOccurs="0" name="status" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="OrderNotFoundFaultType">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="orderID" type="xsd:unsignedInt"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="PurchaseOrder">
<wsdl:part name="parameters" element="tns:PurchaseOrderType"/>
</wsdl:message>
<wsdl:message name="OrderConfirmation">
<wsdl:part name="parameters" element="tns:OrderConfirmationType"/>
</wsdl:message>
<wsdl:message name="GetOrderStatus">
<wsdl:part name="parameters" element="tns:GetOrderStatusType"/>
</wsdl:message>
<wsdl:message name="GetOrderStatusResponse">
<wsdl:part name="parameters" element="tns:GetOrderStatusResponseType"/>
</wsdl:message>
<wsdl:message name="OrderNotFoundFault">
<wsdl:part name="parameters" element="tns:OrderNotFoundFaultType"/>
</wsdl:message>
<wsdl:portType name="IPurchaseOrder">
<wsdl:operation name="Order">
<wsdl:input message="tns:PurchaseOrder" wsaw:Action="http://example.org/purchaseorder"/>
<wsdl:output message="tns:OrderConfirmation" wsaw:Action="http://example.org/orderconfirmation"/>
</wsdl:operation>
<wsdl:operation name="OrderStatus">
<wsdl:input message="tns:GetOrderStatus" wsaw:Action="http://example.org/getorderstatus"/>
<wsdl:output message="tns:GetOrderStatusResponse" wsaw:Action="http://example.org/getorderstatusresponse"/>
<wsdl:fault name="OrderNotFound" message="tns:OrderNotFoundFault" wsaw:Action="http://example.org/ordernotfound"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="PurchaseOrderBinding" type="tns:IPurchaseOrder">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Order">
<soap:operation soapAction="http://example.org/purchaseorder" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="OrderStatus">
<soap:operation soapAction="http://example.org/getorderstatus" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="OrderNotFound">
<soap:body use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="PurchaseOrderService">
<wsdl:port name="IPurchaseOrder" binding="tns:PurchaseOrderBinding">
<soap:address location="http://example.org/IPurchaseOrder"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Makefile
#------------------------------------------------------------
# Copyright (C) Microsoft. All rights reserved.
#------------------------------------------------------------
!include <Win32.Mak>
EXTRA_LIBS = WebServices.lib rpcrt4.lib Iphlpapi.lib
all: $(OUTDIR) $(OUTDIR)\WsOneWayUdpServer.exe
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
$(OUTDIR)\PurchaseOrder.wsdl.c: PurchaseOrder.wsdl
Wsutil.exe /wsdl:PurchaseOrder.wsdl /string:WS_STRING /out:$(OUTDIR)
$(OUTDIR)\PurchaseOrder.wsdl.obj: $(OUTDIR)\PurchaseOrder.wsdl.c
$(cc) $(cdebug) $(cflags) $(cvarsmt) /WX -I$(OUTDIR) /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" $(OUTDIR)\PurchaseOrder.wsdl.c
$(OUTDIR)\OneWayUdpServer.obj: OneWayUdpServer.cpp $(OUTDIR)\PurchaseOrder.wsdl.c
$(cc) $(cdebug) $(cflags) $(cvarsmt) /WX -I$(OUTDIR) /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" OneWayUdpServer.cpp
$(OUTDIR)\WsOneWayUdpServer.exe: $(OUTDIR)\OneWayUdpServer.obj $(OUTDIR)\PurchaseOrder.wsdl.obj
$(link) $(ldebug) $(conlflags) $(conlibsmt) $(EXTRA_LIBS) -out:$(OUTDIR)\WsOneWayUdpServer.exe $(OUTDIR)\OneWayUdpServer.obj $(OUTDIR)\PurchaseOrder.wsdl.obj /PDB:$(OUTDIR)\WsOneWayUdpServer.PDB
clean:
$(CLEANUP)
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour