Win32 thread completion port

Source: Internet
Author: User
Tags htons
 

Server of port completion

/** Echosrv. c ** sample code for multithreading applications in Win32 * this is from chapter 6, listing 6-4 ** demonstrates how to use I/O Completion Ports * with TCP on the Internet. this sample * server can only be run on Windows NT, * version 3.51 or later. the client (echocli) * can be run on Windows 95. */# define win32_lean_and_mean # include <stdio. h> # include <stdlib. h> # include <windows. h> # I Nclude <tchar. h> # include <string. h> # include <Winsock. h> # include <Io. h> # include "mtverify. H "// pick a port number that seems to be away from all others # define serv_tcp_port 5554 # define maxline 512 // structure definition // The context key keeps track how the I/O // is progressing for each individual file handle. struct contextkey {socket sock; // input char inbuffer [4]; overlapped ovin; // outp Ut int noutbufindex; // total byte intncurrentbufindex; // Number of reads each time char outbuffer [maxline]; overlapped ovout; DWORD dwwritten ;}; /// global variables // handle ghcompletionport; // function prototypes // void createworkerthreads (); DWORD winapi threadfunc (lpvoid pvoid ); void issueread (struct contextkey * pcntx); void checkosversion (); void fatalError (char * s ); //////////////////////////////////////// /// // int Main (INT argc, char * argv []) {socket listener; socket newsocket; wsadata; struct sockaddr_in serveraddress; struct sockaddr_in clientaddress; int clientaddresslength; int err; checkosversion (); err = wsastartup (0x0101, & wsadata); If (ERR = socket_error) {fatalError ("wsastartup failed"); Return exit_failure ;} /** open a TCP socket connection to the server * by default, a socket is alw Ays opened * For overlapped I/O. do not attach this * socket (listener) to the I/O completion * port! */Listener = socket (af_inet, sock_stream, 0); If (listener <0) {fatalError ("socket () failed"); Return exit_failure ;} /** bind our local address */memset (& serveraddress, 0, sizeof (serveraddress); serveraddress. sin_family = af_inet; serveraddress. sin_addr.s_addr = htonl (inaddr_any); // inet_addr serveraddress. sin_port = htons (serv_tcp_port); err = BIND (listener, (struct sockaddr *) & serveraddres S, sizeof (serveraddress); If (ERR <0) fatalError ("BIND () failed"); ghcompletionport = createiocompletionport (invalid_handle_value, null, // No prior port 0, // No Key 0 // use default # of threads); If (ghcompletionport = NULL) fatalError ("createiocompletionport () failed"); createworkerthreads (ghcompletionport); Listen (listener, 5); fprintf (stderr, "echo server with I/O Completion Ports \ n "); Fprintf (stderr, "running on TCP port % d \ n", serv_tcp_port); fprintf (stderr, "\ npress Ctrl + C to stop the server \ n "); /// loop forever accepting requests new connections // and starting reading from them. // For (;) {struct contextkey * pkey; clientaddresslength = sizeof (clientaddress); newsocket = accept (listener, (struct sockaddr *) & clientaddress, & clientaddresslength ); if (newsocket <0) {fa Talerror ("accept () failed"); Return exit_failure;} // create a context key and initialize it. // calloc will zero the buffer pkey = calloc (1, sizeof (struct contextkey); pkey-> sock = newsocket; pkey-> ovout. hevent = createevent (null, true, false, null); // set the event for writing so that packets // will not be sent to the completion port when/A write finishes. pkey-> ovout. hevent = (handle) (d Word) pkey-> ovout. hevent | 0x1); // associate the socket with the completion port createiocompletionport (handle) newsocket, ghcompletionport, (DWORD) pkey, // No Key 0 // use default # of threads); // kick off the first read issueread (pkey);} return 0;} void createworkerthreads () {system_info sysinfo; DWORD dwthreadid; DWORD dwthreads; dword I; getsysteminfo (& sysinfo); dwthreads = sysinfo. dwnumber Ofprocessors * 2 + 2; for (I = 0; I <dwthreads; I ++) {handle hthread; hthread = createthread (null, 0, threadfunc, null, 0, & dwthreadid); closehandle (hthread) ;}/// each worker thread starts here. DWORD winapi threadfunc (lpvoid pvoid) {bool bresult; DWORD dwnumread; struct contextkey * pcntx; lpoverlapped metadata; convert (pvoid); // loop forever on getting packets from // The I/ O completion port. for (;) {bresult = getqueuedcompletionstatus (ghcompletionport, & dwnumread, & (DWORD) pcntx, & lpoverlapped, infinite); If (bresult = false & lpoverlapped = NULL) {fatalError ("threadfunc-illegal call to getqueuedcompletionstatus");} else if (bresult = false & lpoverlapped! = NULL) {// This happens occasionally instead of // end-of-file. not sure why. closesocket (pcntx-> sock); free (pcntx); fprintf (stderr, "threadfunc-I/O operation failed \ n");} else if (dwnumread = 0) {closesocket (pcntx-> sock); free (pcntx); fprintf (stderr, "threadfunc-end of file. \ n ");} // got a valid data block! // Save the data to our buffer and write it // All back out (echo it) if we have see A \ n else {// figure out where in the buffer to save the character // char * PCH = & pcntx-> outbuffer [pcntx-> noutbufindex ++]; memcpy (pcntx-> outbuffer + pcntx-> noutbufindex, pcntx-> inbuffer, pcntx-> ncurrentbufindex); pcntx-> noutbufindex + = pcntx-> ncurrentbufindex; /// * PCH ++ = pcntx-> inbuffer [0]; // * PCH = '\ 0'; // Debugging, writefile doesn't care if (pcntx-> inbuffer [pcntx-> ncurrentbufindex-1] = '\ n ') {pcntx-> outbuffer [pcntx-> noutbufindex] = '\ 0'; writefile (handle) (pcntx-> sock), pcntx-> outbuffer, pcntx-> noutbufindex, & pcntx-> dwwritten, & pcntx-> ovout); pcntx-> noutbufindex = 0; fprintf (stderr, "echo on socket % x. \ n ", pcntx-> sock);} // start a new read issueread (pcntx) ;}} return 0 ;}/ ** call readfile To start an overlapped Request * On a socket. make sure we handle errors * That are recoverable. */void issueread (struct contextkey * pcntx) {int I = 0; bool bresult; int err; int numread; while (++ I) {// request a single character bresult = readfile (handle) pcntx-> sock, pcntx-> inbuffer, 1, // number of records accepted each time & numread, & pcntx-> ovin); // It succeeded immediately, but do not process it // here, wait for Completion packet. if (bresult) {pcntx-> ncurrentbufindex = numread; return;} err = getlasterror (); // This is what we want to happen, it's not an error if (ERR = error_io_pending) return; // handle recoverable error if (ERR = error_invalid_user_buffer | err = role | err = error_not_enough_memory) {if (I = 5) // I just picked a number {sleep (50); // wait around and try Later continue;} fatalError ("issueread-system ran out of non-paged space");} break;} fprintf (stderr, "issueread-readfile failed. \ n ") ;}/// make sure we are running under the right versions // of Windows NT (3.51, 4.0, or later) // void checkosversion () {osversioninfo ver; bool bresult; ver. dwosversioninfosize = sizeof (osversioninfo); bresult = getversionex (lposversioninfo) & Ver); If ((! Bresult) | (ver. dwplatformid! = Ver_platform_win32_nt) {fatalError ("echosrv requires Windows NT 3.51 or later. ") ;}//// error handler // void fatalError (char * s) {fprintf (stdout," % s \ n ", S ); exit (exit_failure );}
Client with completed Port
/* * EchoCli.c * * Sample code for "Multithreading Applications in Win32" * This is from Chapter 6. * * This is a command line client to drive the ECHO server. * Run the server in one Commmand Prompt Window, * then run this program in one or more other windows. * EchoCli will wait for you to type in some text when * it starts up. Each line of text will be sent to the * echo server on TCP port 5554. */#include <windows.h>#include <tchar.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <winsock.h>/* Function Prototypes */void FatalError(char *s);int writen(SOCKET sock, char *ptr, int nBytes);int readline(SOCKET sock, char *ptr, int maxlen);void DoClientLoop(FILE *fp, SOCKET sock);/* Constants */#define MAXLINE 512#define SERVER_TCP_PORT5554#define SERVER_ADDRESS"127.0.0.1"/* * Error handler */void FatalError(char *s){    fprintf(stdout, "%s\n", s);    exit(EXIT_FAILURE);}/* * Write bytes to the port with proper block size handling. */int writen(SOCKET sock, char *ptr, int nBytes){    int nleft;    int nwritten;    nleft = nBytes;    while (nleft > 0)    {       nwritten = send(sock,                   ptr,                   nBytes,                   0          );       if (nwritten == SOCKET_ERROR)       {          fprintf(stdout, "Send Failed\n");          exit(1);       }        nleft -= nwritten;        ptr += nwritten;    }    return nBytes - nleft;}/* * Read a line of text of the port. This version * is very inefficient, but it's simple. */int readline(SOCKET sock, char *ptr, int maxlen){    int n;    int rc;    char c;    for (n=1; n<maxlen; n++)    {        if ( ( rc= recv(sock, &c, 1, 0)) == 1)        {            *ptr++ = c;            if (c=='\n')                break;        }        else if (rc == 0)        {            if (n == 1)                return 0;            else                break;        }        else            return -1;  /* Error */    }    *ptr = '\0';    return n;}int main(int argc, char *argv[]){    WSADATA WsaData;    SOCKET sock;    struct sockaddr_in  serv_addr;    int err;    puts("EchoCli - client for echo server sample program\n");    puts("Type a line of text followed by Return.");    puts("Exit this program by typing Ctrl+Z followed by Return.");    err = WSAStartup(0x0101, &WsaData);    if (err == SOCKET_ERROR)        FatalError("WSAStartup Failed");    /*     * Bind our local address     */    memset(&serv_addr, 0, sizeof(serv_addr));    serv_addr.sin_family    = AF_INET;    // Use the local host    serv_addr.sin_addr.s_addr   = inet_addr(SERVER_ADDRESS);    serv_addr.sin_port          = htons(SERVER_TCP_PORT);    /*     * Open a TCP socket (an Internet stream socket)     */    sock = socket(AF_INET, SOCK_STREAM, 0);    if (sock < 0)        FatalError("socket() failed -- do you have TCP/IP networking installed?");    if (connect(sock, (struct sockaddr *) &serv_addr,                sizeof(serv_addr)) < 0)        FatalError("connect() failed -- is the server running?");    DoClientLoop(stdin, sock);    closesocket(sock);    return EXIT_SUCCESS;}/* * As long as there is input from "fp", copy it to * the server, read what the server gives back, * and print it. */void DoClientLoop(FILE *fp, SOCKET sock){    int n;    char sendline[MAXLINE];    char recvline[MAXLINE+1];    while (fgets(sendline, MAXLINE, fp) != NULL)    {        n = strlen(sendline);        if (writen(sock, sendline, n) != n)            FatalError("DoClientLoop: writen() error");        n = readline(sock, recvline, MAXLINE);        if (n < 0)            FatalError("DoClientLoop: readline() error");        recvline[n] = '\0';        fputs(recvline, stdout);    }    if (ferror(fp))        FatalError("DoClientLoop: error reading file");}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.