WSOCK.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:38k
源码类别:
Windows编程
开发平台:
Visual C++
- //-----------------------------------------------------------------------------
- // This is a part of the Microsoft Source Code Samples.
- // Copyright (C) 1993-1997 Microsoft Corporation.
- // All rights reserved.
- //
- // This source code is only intended as a supplement to
- // Microsoft Development Tools and/or WinHelp documentation.
- // See these sources for detailed information regarding the
- // Microsoft samples programs.
- //-----------------------------------------------------------------------------
- /****************************************************************************
- * wsock.c -- sample program demonstrating Windows Sockets APIs.
- *
- * Demonstrates basic sockets programming with the Windows Sockets API.
- * Allows two occurances of the application to connect. Also, displays
- * information about a host computer.
- *
- ****************************************************************************/
- #include <windows.h> /* required for all Windows applications */
- #include <stdio.h> /* for sprintf */
- #include <string.h> /* for strlen */
- #include <memory.h>
- #include <process.h> /* for _beginthread */
- #include "wsock.h" /* specific to this program */
- HANDLE hInst; /* current instance */
- SOCKET sock;
- u_short portno; /* Which tcp port are we going to use? */
- char szBuff[ 80 ]; /* Temp buffer - used to pass strings */
- /* to and from dialog boxes, etc */
- char gpszHelloWorld[]= "Hello World.";
- #define MAX_PENDING_CONNECTS 4 /* The backlog allowed for listen() */
- #define NO_FLAGS_SET 0 /* Used with recv()/send() */
- #define MY_MSG_LENGTH 80 /* msg buffer sent back and forth */
- /****************************************************************************
- *
- * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
- *
- * PURPOSE: calls initialization function, processes message loop
- *
- ****************************************************************************/
- WINAPI WinMain(
- HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow
- )
- {
- MSG msg;
- UNREFERENCED_PARAMETER( lpCmdLine );
- if (!hPrevInstance) /* Other instances of app running? */
- if (!InitApplication(hInstance)) /* Initialize shared things */
- return (FALSE); /* Exits if unable to initialize */
- /*
- * Perform initializations that apply to a specific instance
- */
- if (!InitInstance(hInstance, nCmdShow))
- return (FALSE);
- /*
- * Acquire and dispatch messages until a WM_QUIT message is received.
- */
- while (GetMessage(&msg, /* message structure */
- NULL, /* handle of window receiving the message */
- 0, /* lowest message to examine */
- 0)) /* highest message to examine */
- {
- TranslateMessage(&msg); /* Translates virtual key codes */
- DispatchMessage(&msg); /* Dispatches message to window */
- }
- return (msg.wParam); /* Returns the value from PostQuitMessage */
- }
- /****************************************************************************
- *
- * FUNCTION: InitApplication(HANDLE)
- *
- * PURPOSE: Initializes window data and registers window class
- *
- ****************************************************************************/
- BOOL InitApplication(HANDLE hInstance) /* current instance */
- {
- WNDCLASS wc;
- /* Fill in window class structure with parameters that describe the */
- /* main window. */
- wc.style = 0; /* Class style(s). */
- wc.lpfnWndProc = (WNDPROC)MainWndProc; /* Function to retrieve messages for */
- /* windows of this class. */
- wc.cbClsExtra = 0; /* No per-class extra data. */
- wc.cbWndExtra = 0; /* No per-window extra data. */
- wc.hIcon = LoadIcon (hInstance, "wsockicon"); /* Icon name from .RC */
- wc.hInstance = hInstance; /* Application that owns the class. */
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = "WSockMenu"; /* Name of menu resource in .RC file. */
- wc.lpszClassName = "WSockWClass"; /* Name used in call to CreateWindow. */
- /* Register the window class and return success/failure code. */
- return (RegisterClass(&wc));
- }
- /****************************************************************************
- *
- * FUNCTION: InitInstance(HANDLE, int)
- *
- * PURPOSE: Saves instance handle and creates main window
- *
- ****************************************************************************/
- BOOL InitInstance(
- HANDLE hInstance, /* Current instance identifier. */
- int nCmdShow) /* Param for first ShowWindow() call. */
- {
- HWND hWnd; /* Main window handle. */
- /* Save the instance handle in static variable, which will be used in */
- /* many subsequence calls from this application to Windows. */
- hInst = hInstance;
- /* Create a main window for this application instance. */
- hWnd = CreateWindow(
- "WSockWClass", /* See RegisterClass() call. */
- "Windows Sockets Sample Application", /* Text for window title bar. */
- WS_OVERLAPPEDWINDOW, /* Window style. */
- CW_USEDEFAULT, /* Default horizontal position. */
- CW_USEDEFAULT, /* Default vertical position. */
- CW_USEDEFAULT, /* Default width. */
- CW_USEDEFAULT, /* Default height. */
- NULL, /* Overlapped windows have no parent. */
- NULL, /* Use the window class menu. */
- hInstance, /* This instance owns this window. */
- NULL /* Pointer not needed. */
- );
- /* If window could not be created, return "failure" */
- if (!hWnd)
- return (FALSE);
- /* Make the window visible; update its client area; and return "success" */
- ShowWindow(hWnd, nCmdShow); /* Show the window */
- UpdateWindow(hWnd); /* Sends WM_PAINT message */
- return (TRUE); /* Returns the value from PostQuitMessage */
- }
- /****************************************************************************
- *
- * FUNCTION: AcceptThreadProc(PTHREADPACK tp)
- *
- * PURPOSE: Use blocking accept() calls and display a message box when
- * a connection is made.
- *
- ****************************************************************************/
- void AcceptThreadProc( PTHREADPACK ptp )
- {
- SOCKADDR_IN acc_sin; /* Accept socket address - internet style */
- int acc_sin_len; /* Accept socket address length */
- int status;
- char szMsg[ MY_MSG_LENGTH ];
- acc_sin_len = sizeof(acc_sin);
- wsprintf( szBuff, "thread #%d created.", ptp->nThread);
- MessageBox(ptp->hWnd, szBuff, "FYI", MB_OK);
- sock = accept( sock,(struct sockaddr FAR *) &acc_sin,
- (int FAR *) &acc_sin_len );
- if (sock < 0) {
- sprintf(szBuff, "%d is the error", WSAGetLastError());
- MessageBox(ptp->hWnd, szBuff, "accept(sock) failed", MB_OK);
- }
- wsprintf( szBuff, "Thread #%d accepted somethingnnCheck for incoming messages?", ptp->nThread);
- /*
- * Now have a connection --
- * SetConnectMenus() grays/enables proper menu items
- */
- SetConnectMenus( ptp->hWnd );
- while (1) {
- /*
- * By default sockets are created in blocking mode.
- * Just keep reading until process destroyed.
- */
- status = recv( sock, szMsg, MY_MSG_LENGTH, NO_FLAGS_SET );
- if (status == SOCKET_ERROR) {
- wsprintf( szMsg, "Error %d", WSAGetLastError() );
- MessageBox( ptp->hWnd, szMsg, "Error with recv()", MB_OK);
- _endthread();
- }
- szMsg[status] = ' '; /* NULL-terminate the string */
- if (status)
- MessageBox( ptp->hWnd, szMsg, "From thread", MB_OK);
- else {
- MessageBox( ptp->hWnd, "Connection broken", "Error", MB_OK);
- _endthread();
- }
- } /* while (forever) */
- }
- /****************************************************************************
- *
- * FUNCTION: FillAddr(HWND, PSOCKADDR_IN, BOOL)
- *
- * PURPOSE: Retrieves the IP address and port number.
- *
- * COMMENTS:
- * This function is called in two conditions.
- * 1.) When a client is preparing to call connect(), or
- * 2.) When a server host is going to call bind(), listen() and
- * accept().
- * In both situations, a SOCKADDR_IN structure is filled.
- * However, different fields are filled depending on the condition.
- *
- * ASSUMPTION:
- * szBuff is a global variable that contains the remote host name or NULL
- * if local.
- * bClient determines if this is being called by a client ( will be
- * performing a connect ) or a server ( will be listening )
- *
- *
- ****************************************************************************/
- BOOL FillAddr(
- HWND hWnd,
- PSOCKADDR_IN psin,
- BOOL bClient)
- {
- DWORD dwSize;
- PHOSTENT phe;
- PSERVENT pse;
- char szTemp[200];
- int status;
- psin->sin_family = AF_INET;
- /*
- * If we are setting up for a listen() call (bConnect = FALSE),
- * fill servent with our address.
- */
- if (bClient) {
- phe = gethostbyname(szBuff);
- if (phe == NULL) {
- sprintf(szTemp, "%d is the error. Make sure '%s' is listed in the hosts file.", WSAGetLastError(), szBuff);
- MessageBox(hWnd, szTemp, "gethostbyname() failed.", MB_OK);
- return FALSE;
- }
- memcpy((char FAR *)&(psin->sin_addr), phe->h_addr,
- phe->h_length);
- }
- else { // server
- /*
- * Retrieve my ip address. Assuming the hosts file in
- * in %systemroot%/system/drivers/etc/hosts contains my computer name.
- */
- dwSize = sizeof(szBuff);
- gethostname(szBuff, dwSize);
- psin->sin_addr.s_addr = INADDR_ANY;
- }
- /*
- * Retrieve the Port number
- */
- status = DialogBox(hInst, /* current instance */
- "TCPPORTNUM", /* resource to use */
- hWnd, /* parent handle */
- GetTcpPort); /* instance address */
- switch(status) {
- case 0: /* User cancelled request from prev. dialog box */
- return FALSE;
- case 1: /* actual port number entered */
- psin->sin_port = htons(portno); /* Convert to network ordering */
- break;
- case 2: /* service name entereted */
- /*
- * Find the service name, szBuff, which is a type tcp protocol in
- * the "services" file.
- */
- pse = getservbyname(szBuff, "tcp");
- if (pse == NULL) {
- sprintf(szBuff, "%d is the error. Make sure this is a valid TCP service.", WSAGetLastError());
- MessageBox(hWnd, szBuff, "getservbyname(sock) failed", MB_OK);
- return FALSE;
- }
- psin->sin_port = pse->s_port;
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- /****************************************************************************
- *
- * FUNCTION: SetConnectMenus( HWND )
- *
- * PURPOSE: Gray/Enable the proper menu items after a connection has been
- * established.
- *
- ****************************************************************************/
- void SetConnectMenus( HWND hWnd )
- {
- /*
- * Disable/enable proper menu items.
- */
- EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_ENABLED );
- EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_GRAYED );
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_GRAYED );
- EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_GRAYED );
- EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_GRAYED );
- EnableMenuItem(GetMenu( hWnd ), IDM_CANCEL, MF_GRAYED );
- EnableMenuItem(GetMenu( hWnd ), IDM_SENDTCP, MF_ENABLED );
- EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_GRAYED );
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_GRAYED );
- /*
- * Reflect socket connection in title bar.
- */
- SetWindowText( hWnd, "Connected");
- }
- /****************************************************************************
- *
- * FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
- *
- * PURPOSE: Processes main window messages
- *
- * MESSAGES:
- * WM_CREATE - call WSAStartUp() and display description message
- * WSA_ACCEPT - User-defined message used with WSAAsyncSelect(). Sent
- * by the Windows Sockets DLL when a socket connection is
- * pending.
- *
- * WM_COMMAND
- * IDM_CONNECT - Connect to a remote host.
- * IDM_LISTEN - Use the BSD-Style accept().
- * IDM_ALISTEN - Use the Windows Sockets Asynchronous APIs to detect when
- * a connection is made.
- * IDM_CANCEL - Cancel the Asynchronous call above.
- * IDM_TLISTEN - Uses two threads to accept network connections (using the
- * BSD-Style accept().
- * IDM_HOSTNAME- Display information about a host.
- * IDM_ABOUT - About box.
- *
- * WM_DESTROY - destroy window and call the WSACleanUp()
- *
- ****************************************************************************/
- LONG APIENTRY MainWndProc(
- HWND hWnd, /* window handle */
- UINT message, /* type of message */
- UINT wParam, /* additional information */
- LONG lParam) /* additional information */
- {
- int status; /* Status Code */
- SOCKADDR_IN local_sin; /* Local socket - internet style */
- SOCKADDR_IN acc_sin; /* Accept socket address - internet style */
- int acc_sin_len; /* Accept socket address length */
- switch (message) {
- case WM_CREATE:
- {
- WSADATA WSAData;
- char szTemp[80];
- if ((status = WSAStartup(MAKEWORD(1,1), &WSAData)) == 0) {
- MessageBox( hWnd, WSAData.szDescription, WSAData.szSystemStatus, MB_OK);
- }
- else {
- sprintf(szTemp, "%d is the err", status);
- MessageBox( hWnd, szTemp, "Error", MB_OK);
- }
- }
- break; /* WM_CREATE */
- /*
- * Notification if data is waiting on a socket. This comes
- * from Windows Sockets (via WSAAsyncSelect()).
- */
- case WSA_READ:
- {
- char szTemp[ MY_MSG_LENGTH ];
- if (WSAGETSELECTEVENT(lParam) == FD_READ) {
- status = recv((SOCKET)wParam, szTemp, MY_MSG_LENGTH, NO_FLAGS_SET );
- if (status) {
- szTemp[ status ] = ' ';
- MessageBox( hWnd, szTemp, "WSA_READ", MB_OK);
- }
- else
- MessageBox( hWnd, "Connection broken", "Error", MB_OK);
- }
- else { /* FD_CLOSE -- connection dropped */
- MessageBox( hWnd, "Connection lost", "WSA_READ", MB_OK);
- EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CANCEL, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_SENDTCP, MF_GRAYED);
- }
- }
- break; /* WSA_READ*/
- case WSA_ACCEPT: /* Notification if a socket connection is pending. */
- /*
- * Disable/enable proper menu items.
- */
- EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CANCEL, MF_GRAYED);
- if (WSAGETSELECTERROR( lParam ) == 0) { /* Success */
- /*
- * Accept the incoming connection.
- */
- acc_sin_len = sizeof( acc_sin );
- sock = accept( sock,(struct sockaddr FAR *) &acc_sin,
- (int FAR *) &acc_sin_len );
- if (sock < 0) {
- sprintf(szBuff, "%d is the error", WSAGetLastError());
- MessageBox(hWnd, szBuff, "accept(sock) failed", MB_OK);
- break;
- }
- MessageBox(hWnd, "accept()", "Accepted a connection!", MB_OK);
- /*
- * Now have a connection --
- * SetConnectMenus() grays/enables proper menu items
- */
- SetConnectMenus( hWnd );
- /*
- * Send main window a WSA_READ when either data is pending on
- * the socket (FD_READ) or the connection is closed (FD_CLOSE)
- */
- if ((status = WSAAsyncSelect( sock, hWnd, WSA_READ, FD_READ | FD_CLOSE )) > 0) {
- wsprintf(szBuff, "%d (0x%x)", status, status);
- MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK);
- closesocket( sock );
- }
- }
- else {
- MessageBox(hWnd, "accept()", "Error occured!", MB_OK);
- /*
- * Cancel any further notifications.
- */
- WSAAsyncSelect( sock, hWnd, 0, 0);
- SetWindowText( hWnd, "Async Listen call canceled");
- }
- break; /* WSA_ACCEPT */
- case WM_COMMAND: /* message: command from application menu */
- switch(LOWORD(wParam)) {
- case IDM_CONNECT: /* Client - connect to remote host */
- {
- /*
- When a network client wants to connect to a server,
- it must have:
- 1.) a TCP port number (gotten via getservbyname())
- and
- 2.) an IP address of the remote host (gotten via gethostbyname()).
- The following summarizes the steps used to connect.
- Make a dialog box (HostName)
- Get the name of the remote host computer in which
- to connect from the user (store string in "szBuff" global var)
- * Check to see if the hosts file knows the computer (gethostbyname)
- * Get the host information (hostent structure filled)
- * Fill in the address of the remote host into the servent structure (memcpy)
- * Make a dialog box (TCPPORTNUM)
- * Get the NAME of the port to connect to on the remote host from the
- user.
- * Get the port number (getservbyname)
- * Fill in the port number of the servent structure
- Establish a connection (connect)
- The * prefixed steps are done in the FillAddr() procedure.
- */
- SOCKADDR_IN dest_sin; /* DESTination Socket INternet */
- /* Get the name of the remote host. Store the string in szBuff. */
- status = DialogBox(hInst,
- "HOSTNAME",
- hWnd,
- GetHostName);
- if (!status) /* User cancelled request from prev. dialog box */
- break;
- sock = socket( AF_INET, SOCK_STREAM, 0);
- if (sock == INVALID_SOCKET) {
- MessageBox(hWnd, "socket() failed", "Error", MB_OK);
- break;
- }
- /*
- * Retrieve the IP address and TCP Port number
- * Global variable szBuff contains the remote host name.
- */
- if (!FillAddr( hWnd, &dest_sin, TRUE)) {
- closesocket( sock );
- break;
- }
- if (connect( sock, (PSOCKADDR) &dest_sin, sizeof( dest_sin)) < 0) {
- closesocket( sock );
- MessageBox(hWnd, "connect() failed", "Error", MB_OK);
- break;
- }
- MessageBox(hWnd, "connect() worked!", "Success!", MB_OK);
- /*
- * Now have a connection --
- * SetConnectMenus() grays/enables proper menu items
- */
- SetConnectMenus( hWnd );
- /*
- * Send main window a WSA_READ when either data is pending on
- * the socket (FD_READ) or the connection is closed (FD_CLOSE)
- */
- if ((status = WSAAsyncSelect( sock, hWnd, WSA_READ, FD_READ | FD_CLOSE )) > 0) {
- wsprintf(szBuff, "%d (0x%x)");
- MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK);
- closesocket( sock );
- }
- }
- break; /* IDM_CONNECT */
- case IDM_CONNECTANDSEND:
- {
- //
- //
- // In order to simulate a more typical real-world client, here
- // we make the connection, and then immediately send it data.
- //
- // See IDM_CONNECT above for full comments.
- SOCKADDR_IN dest_sin;
- status = DialogBox(hInst,
- "HOSTNAME",
- hWnd,
- GetHostName);
- if (!status)
- break;
- sock = socket( AF_INET, SOCK_STREAM, 0);
- if (sock == INVALID_SOCKET) {
- MessageBox(hWnd, "socket() failed", "Error", MB_OK);
- break;
- }
- if (!FillAddr( hWnd, &dest_sin, TRUE)) {
- closesocket( sock );
- break;
- }
- if (connect( sock, (PSOCKADDR) &dest_sin, sizeof( dest_sin)) < 0) {
- MessageBox(hWnd, "connect() failed", "Error", MB_OK);
- closesocket( sock );
- break;
- }
- if (send (sock, gpszHelloWorld, lstrlen (gpszHelloWorld), 0 ) == SOCKET_ERROR) {
- wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError());
- MessageBox( hWnd, szBuff, "Error on send()", MB_OK);
- closesocket( sock );
- break;
- }
- MessageBox(hWnd, "connect() & send() worked!", "Success!", MB_OK);
- SetConnectMenus( hWnd );
- if ((status = WSAAsyncSelect( sock, hWnd, WSA_READ, FD_READ | FD_CLOSE )) > 0) {
- wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError());
- MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK);
- closesocket( sock );
- }
- }
- break; // IDM_CONNECTANDSEND
- case IDM_ACCEPTEX:
- {
- //
- // Demonstrate the use of AcceptEx().
- //
- #define MAX_BYTES 2000
- #define PADDED_ADDR_SIZE sizeof(SOCKADDR_IN)+16
- SOCKET sListenSocket;
- SOCKET sAcceptSocket;
- char pData [MAX_BYTES];
- OVERLAPPED olResult;
- DWORD dwBytes;
- //
- // For this API, we need to create two sockets ahead of time.
- // The listen socket goes through the standard bind/listen steps.
- //
- sListenSocket = socket( AF_INET, SOCK_STREAM, 0);
- sAcceptSocket = socket( AF_INET, SOCK_STREAM, 0);
- if ((sListenSocket == INVALID_SOCKET) || (sAcceptSocket == INVALID_SOCKET)) {
- MessageBox(hWnd, "sock == INVALID_SOCKET", "socket() failed", MB_OK);
- closesocket(sListenSocket);
- closesocket(sAcceptSocket);
- break;
- }
- //
- // Retrieve the IP address and TCP Port number
- //
- if (!FillAddr(hWnd, &local_sin, FALSE ))
- break;
- //
- // Associate an address with the socket
- //
- if (bind( sListenSocket, (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) {
- wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError());
- MessageBox(hWnd, szBuff, "bind(sock) failed", MB_OK);
- break;
- }
- //
- // And go into the listening state.
- //
- if (listen( sListenSocket, MAX_PENDING_CONNECTS ) < 0) {
- wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError());
- MessageBox(hWnd, szBuff, "listen(sock) failed", MB_OK);
- break;
- }
- //
- // Disable/enable proper menu items.
- //
- EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_GRAYED);
- SetWindowText( hWnd, "AcceptEx..");
- //
- // Create an event for our overlapped structure (required).
- //
- memset (&olResult, 0, sizeof(olResult));
- olResult.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- dwBytes = 0;
- //
- // AcceptEx makes the most sense when used with I/O
- // CompletionPorts and TransmitFile.
- // We show a very basic usage here...
- //
- if (AcceptEx( sListenSocket,
- sAcceptSocket,
- pData,
- MAX_BYTES - 2*PADDED_ADDR_SIZE,
- PADDED_ADDR_SIZE,
- PADDED_ADDR_SIZE,
- &dwBytes,
- &olResult) == FALSE) {
- if (WSAGetLastError() != ERROR_IO_PENDING) {
- wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError());
- MessageBox( hWnd, szBuff, "Error on AcceptEx()", MB_OK);
- break;
- } else {
- //
- // In our contrived scenario, we expect GetLastError to be
- // ERROR_IO_PENDING. A real app would do other work.
- // Since this is a simple sample, we will just block waiting
- // for some input to come through the socket.
- //
- GetOverlappedResult ( (HANDLE) sAcceptSocket,
- &olResult,
- &dwBytes,
- TRUE);
- pData[dwBytes] = 0;
- MessageBox(hWnd, pData, "AcceptEx received data", MB_OK);
- }
- }
- //
- // As per the documentation, poke the new socket so that it will have
- // the correct properties and can be used by other functions.
- //
- if (setsockopt( sAcceptSocket,
- SOL_SOCKET,
- SO_UPDATE_ACCEPT_CONTEXT,
- (char *)&sListenSocket,
- sizeof(sListenSocket) )) {
- wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError());
- MessageBox( hWnd, szBuff, "Error in setsockopt()", MB_OK);
- break;
- } else {
- //
- // sAcceptSocket is now OK for use by other functions.
- // set it into our global socket (sock)
- //
- sock = sAcceptSocket;
- }
- //
- // In any case, we are done with our listen socket
- //
- closesocket( sListenSocket );
- //
- // Now have a connection --
- // SetConnectMenus() grays/enables proper menu items
- SetConnectMenus( hWnd );
- //
- // Send main window a WSA_READ when either data is pending on
- // the socket (FD_READ) or the connection is closed (FD_CLOSE)
- if ((status = WSAAsyncSelect( sock, hWnd, WSA_READ, FD_READ | FD_CLOSE )) > 0) {
- wsprintf(szBuff, "%d (0x%x)");
- MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK);
- closesocket( sock );
- }
- }
- break; /* IDM_ACCEPTEX */
- case IDM_LISTEN:
- {
- sock = socket( AF_INET, SOCK_STREAM, 0);
- if (sock == INVALID_SOCKET) {
- MessageBox(hWnd, "socket() failed", "Error", MB_OK);
- closesocket(sock);
- break;
- }
- /*
- * Retrieve the IP address and TCP Port number
- */
- if (!FillAddr(hWnd, &local_sin, FALSE ))
- break;
- /*
- * Disable/enable proper menu items.
- */
- EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_GRAYED);
- SetWindowText( hWnd, "Waiting for connection..");
- /*
- * Associate an address with a socket. (bind)
- */
- if (bind( sock, (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) {
- sprintf(szBuff, "%d is the error", WSAGetLastError());
- MessageBox(hWnd, szBuff, "bind(sock) failed", MB_OK);
- break;
- }
- if (listen( sock, MAX_PENDING_CONNECTS ) < 0) {
- sprintf(szBuff, "%d is the error", WSAGetLastError());
- MessageBox(hWnd, szBuff, "listen(sock) failed", MB_OK);
- break;
- }
- acc_sin_len = sizeof(acc_sin);
- sock = accept( sock,(struct sockaddr FAR *) &acc_sin,
- (int FAR *) &acc_sin_len );
- if (sock < 0) {
- sprintf(szBuff, "%d is the error", WSAGetLastError());
- MessageBox(hWnd, szBuff, "accept(sock) failed", MB_OK);
- break;
- }
- MessageBox(hWnd, "accept()", "Accepted a connection!", MB_OK);
- /*
- * Now have a connection --
- * SetConnectMenus() grays/enables proper menu items
- */
- SetConnectMenus( hWnd );
- /*
- * Send main window a WSA_READ when either data is pending on
- * the socket (FD_READ) or the connection is closed (FD_CLOSE)
- */
- if ((status = WSAAsyncSelect( sock, hWnd, WSA_READ, FD_READ | FD_CLOSE )) > 0) {
- wsprintf(szBuff, "%d (0x%x)");
- MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK);
- closesocket( sock );
- }
- }
- break; /* IDM_LISTEN */
- /*
- * Asynchronous Listen - Using WSA extensions.
- */
- case IDM_ALISTEN:
- {
- sock = socket( AF_INET, SOCK_STREAM, 0);
- if (sock == INVALID_SOCKET) {
- MessageBox(hWnd, "socket() failed", "Error", MB_OK);
- break;
- }
- /*
- * Retrieve the IP address and TCP Port number
- */
- if (!FillAddr( hWnd, &local_sin, FALSE)) {
- closesocket( sock );
- break;
- }
- /*
- * Disable/enable proper menu items.
- */
- EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CANCEL, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_GRAYED);
- SetWindowText( hWnd, "Waiting for connection.. (Async)");
- /*
- * Associate an address with a socket. (bind)
- */
- if (bind( sock, (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) {
- sprintf(szBuff, "%d is the error", WSAGetLastError());
- MessageBox(hWnd, szBuff, "bind(sock) failed", MB_OK);
- closesocket( sock );
- break;
- }
- if (listen( sock, MAX_PENDING_CONNECTS ) < 0) {
- sprintf(szBuff, "%d is the error", WSAGetLastError());
- MessageBox(hWnd, szBuff, "listen(sock) failed", MB_OK);
- break;
- }
- /*
- * Send window a WSA_ACCEPT when something is trying to connect.
- */
- if ((status = WSAAsyncSelect( sock, hWnd, WSA_ACCEPT, FD_ACCEPT)) > 0) {
- wsprintf( szBuff, "%d (0x%x)");
- MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK);
- SetWindowText( hWnd, "Async listen cancelled");
- closesocket( sock );
- }
- }
- break; /* IDM_ALISTEN */
- /*
- * Cancel an asynchronous call.
- */
- case IDM_CANCEL:
- WSAAsyncSelect( sock, hWnd, 0, 0);
- SetWindowText( hWnd, "Async Listen cancelled..");
- /*
- * Disable/enable proper menu items.
- */
- EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CANCEL, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_SENDTCP, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_ENABLED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_ENABLED);
- break; /* IDM_CANCEL */
- /*
- * Listen in the main thread -- spawn and accept two network
- * connections inside two threads.
- */
- case IDM_TLISTEN:
- {
- static THREADPACK tp;
- sock = socket( AF_INET, SOCK_STREAM, 0);
- if (sock == INVALID_SOCKET) {
- MessageBox(hWnd, "socket() failed", "Error", MB_OK);
- closesocket(sock);
- break;
- }
- /*
- * Retrieve the IP address and TCP Port number
- */
- if (!FillAddr(hWnd, &local_sin, FALSE ))
- break;
- /*
- * Disable/enable proper menu items.
- */
- EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_SENDTCP, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_GRAYED);
- EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_GRAYED);
- SetWindowText( hWnd, "Waiting for connection..");
- /*
- * Associate an address with a socket. (bind)
- */
- if (bind( sock, (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) {
- sprintf(szBuff, "%d is the error", WSAGetLastError());
- MessageBox(hWnd, szBuff, "bind(sock) failed", MB_OK);
- break;
- }
- if (listen( sock, MAX_PENDING_CONNECTS ) < 0) {
- sprintf(szBuff, "%d is the error", WSAGetLastError());
- MessageBox(hWnd, szBuff, "listen(sock) failed", MB_OK);
- break;
- }
- tp.nThread = 0;
- tp.hWnd = hWnd;
- _beginthread(AcceptThreadProc, 0, &tp);
- }
- break; /* IDM_TLISTEN */
- /*
- * Display host information.
- */
- case IDM_HOSTNAME:
- /*
- * Prompt the user and retrieve the text name of the host.
- */
- status = DialogBox(hInst,
- "HOSTNAME",
- hWnd,
- GetHostName);
- if (status == TRUE) { /* If user hit "OK" .. */
- /*
- * Get the host information
- */
- if ((phe = gethostbyname( szBuff )) == NULL) {
- MessageBox(hWnd, "gethostbyname() failed", "Error", MB_OK);
- break;
- }
- else {
- /*
- * Display the host information ..
- */
- DialogBox(hInst,
- "DISPLAYHOST",
- hWnd,
- DisplayHostEnt);
- }
- }
- break; /* IDM_HOSTNAME */
- /*
- * Send a message to (via TCP connection) to remote host.
- */
- case IDM_SENDTCP:
- DialogBox(hInst, /* current instance */
- "GetString", /* resource to use */
- hWnd, /* parent handle */
- GetSendString); /* instance address */
- /*
- * Assumption -- The GetString dialog box proc fills the global
- * string buffer, szBuff, with the desired string to send.
- */
- send(sock, szBuff, strlen(szBuff), NO_FLAGS_SET );
- break; /* IDM_SENDTCP */
- case IDM_ABOUT:
- DialogBox(hInst, /* current instance */
- "AboutBox", /* resource to use */
- hWnd, /* parent handle */
- About); /* About() instance address */
- break; /* IDM_ABOUT */
- default:
- /* Lets Windows process it */
- return (DefWindowProc(hWnd, message, wParam, lParam));
- break;
- }
- break;
- /*
- * Clean up. Takes care of any open socket descriptors.
- */
- case WM_DESTROY:
- WSACleanup();
- PostQuitMessage(0);
- break;
- default: /* Passes it on if unproccessed */
- return (DefWindowProc(hWnd, message, wParam, lParam));
- }
- return (0);
- }