Winsock's event IO asynchronous model (continuing to develop network communication program)

zhaozj2021-02-17  46

The classic entry of the development network communication in the previous discussion is the asynchronous I / O model of WSaasyncselect, which will discuss the WSAEventSelect asynchronous I / O model.

The WSAEventSelect model is a bit similar to the WSaasyncselect model, and the difference is that he does not respond to the network event in a message map, but is used to respond to the network event in a way for multiple events. Below is a simple server program for a WSAEventSelectSelect model and a multi-thread mechanism, the application based on the MFC standard dialog. Implement a connection request accepted by multiple clients, and record related information about all clients, displayed in the list box.

// serverdlg.cpp: importation file //

#include "stdafx.h" #include "server.h" #include "serverdlg.h"

#ifdef _debug # define new debug_new # undef this_filestatic char this_file [] = __file __; # ENDIF

Socket accept; file: // Used for new connections for new connections WSAEVENT NEWEVENT; file: / / New event corresponding to new sockets socket socket [WSA_MAXIM_WAIT_EVENTS]; file: // Store all generated sets Sign WSAEVENT EVENT [WSA_MAXIMUM_WAIT_EVENTS]; file: // Store all generated event object int eventtotal; File: // created Total number int index; file: // Waiting for the return value of multiple event functions WSANETWORKEVENTS NETWORKEVENTS; File: // Used to receive network event types that occur on a socket and possible error code

/// Caboutdlg Dialog Used for App About

Class Caboutdlg: public cdialog {public: capoutdlg ();

// Dialog Data file: // {{AFX_DATA (Caboutdlg) enum {IDD = IDD_ABOUTBOX}; file: //}} AFX_DATA

// ClassWizard generated virtual function overrides file: // {{AFX_VIRTUAL (CAboutDlg) protected: virtual void DoDataExchange (CDataExchange * pDX); // DDX / DDV support file: //}} AFX_VIRTUAL

// ImplementationProtace: file: // {{AFX_MSG (Caboutdlg) File: //}} AFX_MSG DECLARE_MESSAGE_MAP ()};

Caboutdlg :: Caboutdlg (): cdialog (Caboutdlg :: IDD) {file: // {{AFX_DATA_INIT (Caboutdlg) File: //}} AFX_DATA_INIT}

Void Caboutdlg :: DODATAEXCHANGE (CDataExchange * PDX) {cdialog :: DODATAEXCHANGE (PDX); file: // {{AFX_DATA_MAP (Caboutdlg) file: //}} AFX_DATA_MAP}

Begin_MESSAGE_MAP (Caboutdlg, cdialog) file: // {{AFX_MSG_MAP (Caboutdlg) // no message handlers file: //}} AFX_MSG_MAPEND_MESSAGE_MAP ()

/// Cserververdlg Dialog

CServerDlg :: CServerDlg (CWnd * pParent / * = NULL * /): CDialog (CServerDlg :: IDD, pParent) {file: // {{AFX_DATA_INIT (CServerDlg) // NOTE: the ClassWizard will add member initialization here file: / /}} AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_Connectnum = 0; m_NetworkID = 0; EventTotal = 0; for (int i = 0; i loadicon (iDR_mainframe);

void CServerDlg :: DoDataExchange (CDataExchange * pDX) {CDialog :: DoDataExchange (pDX); file: // {{AFX_DATA_MAP (CServerDlg) // NOTE: the ClassWizard will add DDX and DDV calls here file: //}} AFX_DATA_MAP}

BEGIN_MESSAGE_MAP (CServerDlg, CDialog) file: // {{AFX_MSG_MAP (CServerDlg) ON_WM_SYSCOMMAND () ON_WM_PAINT () ON_WM_QUERYDRAGICON () ON_WM_TIMER () file: //}} AFX_MSG_MAPEND_MESSAGE_MAP ()

/// cserverdlg Message Handlers

Bool CSERVERDLG :: OnNitdialog () {cdialog :: oninitdialog ();

// Add "About ..." Menu Item to System Menu.

// IDM_ABOUTBOX MUST BE IN THE SYSTEM Command Range. Assert ((idm_aboutbox & 0xff0) == idm_aboutbox; assert (idm_aboutbox <0xf000);

CMenu * pSysMenu = GetSystemMenu (FALSE); if (pSysMenu = NULL!) {CString strAboutMenu; strAboutMenu.LoadString (IDS_ABOUTBOX); if {pSysMenu-> AppendMenu (MF_SEPARATOR) (strAboutMenu.IsEmpty ()!); PSysMenu-> AppendMenu ( MF_String, IDM_AboutBox, Straboutmenu);}}

// set the icon for this dialog. The framework does this automatic or //en the application's main window is not a dialog seticon (m_hicon, true); // set big icon seticon (m_hicon, false); // set small icon / / TODO: Add Extra Initialization Here

Wsadata wsadata; int RET; RET; MakeWord (2, 2), & WSADATA); if (RET! = 0) {MessageBox ("Initializing Socket Failed!"); Return False;}

file: // create a socket m_ListenSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_ListenSocket == INVALID_SOCKET) {MessageBox ( "! Creating socket failed"); closesocket (m_ListenSocket); WSACleanup (); return False;}

File: // Binds to the specified port SockAddr_in localaddr; localaddr.sin_family = af_INet; localaddddddddddddddddddddddddddddddddddddddddddddddddr.sin_addr.s_addr = 0;

if (bind (m_ListenSocket, (const struct sockaddr *) & localaddr, sizeof (sockaddr)) == SOCKET_ERROR) {MessageBox ( "bound address failed!"); closesocket (m_ListenSocket); WSACleanup (); return FALSE;} NewEvent = WSACReateEvent (); file: // Create a new event object

File: // Associate the created event object with the socket created in front, and register Network Event Type IF (WSAEventSELECT (M_ListenSocket, NewEvent, fd_accept | fd_close) == SOCKET_ERROR) {MessageBox ("Register Network Event Failed! "); CloseSocket (M_Listensocket); wsacleanup (); returnaf

File: // Let the created socket in the listening status listen (M_Listensocket, 5);

Event [Eventtotal] = newEvent; socket [Eventtotal] = M_Listensocket; EventTotal ;

File: // Set the image list of the List control Hicon Hicon;

m_imagelist.create (16, 16, 0, 4); // 32, 32 for large icons Hicon = AFXGETAPP () -> loading (idi_client_info); m_imagelist.setbkcolor (RGB (248, 232, 224)); m_imagelist.add (Hicon );

pList = (CListCtrl *) GetDlgItem (IDC_CLIENT_INFO); pList-> SetImageList (& m_imagelist, LVSIL_SMALL); pList-> SetBkColor (RGB (248,232,224)); pList-> SetTextBkColor (RGB (248,232,224));

PLIST-> INSERTCOLUMN (0, "Customer Name", LVCFMT_Center, 90, 0); PLIST-> INSERTCOLUMN (1, "Network ID", LVCFMT_Center, 50, 1); PLIST-> InsertColumn (2, "IP Address", LVCFMT_CENTER, 100, 2); PLIST-> INSERTCOLUMN (3, "Login Time", LVCFMT_Center, 120, 3); PLIST-> InsertColumn (4, "Online Time", LVCFMT_Center, 100, 4); SetTimer (1, 1000 NULL);

File: // Start the core processing thread AFXBEGINTHREAD (KernelWorkthread, this, thread_priority_normal);

Return True; // Return True Unless}

void CServerDlg :: OnSysCommand (UINT nID, LPARAM lParam) {if ((nID & 0xFFF0) == IDM_ABOUTBOX) {CAboutDlg dlgAbout; dlgAbout.DoModal ();} else {CDialog :: OnSysCommand (nID, lParam);}}

// if you add a minimize button to your dialog, you will need the code Below // to draw the icon. For mfc Applications Using the document / view model, // this is automaticly done for you by the framework.

Void CServerdlg :: OnPaint () {if (isiconic ()) {CPAINTDC DC (this); // Device Context for Painting

SendMessage (WM_ICONERASEBKGND, (WPARAM) dc.getsafehdc (), 0);

// Center icon in client rectangle int cxIcon = GetSystemMetrics (SM_CXICON); int cyIcon = GetSystemMetrics (SM_CYICON); CRect rect; GetClientRect (& rect); int x = (rect.Width () - cxIcon 1) / 2; int y = (Rect.height () - Cyicon 1) / 2;

// Draw the icon dc.drawicon (x, y, m_hicon);} else {cdialog :: onpaint ();}}

// the system calls this to obtain the cursor to display while the user dress /// the minimized window.hcursor cserverdlg :: ONQUERYDRAGICON () {Return (hcursor) m_hicon;}

File: // Core processing thread, responding and processes various network events uint kernelworkthread (lpvoid pParam) {int Len = sizeof (sockAddr);

CServerDLG * DLG; DLG = (Cserverdlg *) PPARAM;

while (1) {Index = WSAWaitForMultipleEvents (EventTotal, Event, FALSE, WSA_INFINITE, FALSE); WSAEnumNetworkEvents (Socket [Index - WSA_WAIT_EVENT_0], Event [Index - WSA_WAIT_EVENT_0], & NetworkEvents); if (NetworkEvents.lNetworkEvents & FD_ACCEPT) file: / / Connecting event {if (networkEvents.ierrorcode [fd_accept_bit]! = 0) {DLG-> MessageBox ("Accept connection event failed!"); Break;}

Accept = accept (socket [index - wsa_wait_event_0], (strunt socddr *) & (dlg-> clientaddr), & len); if (accept == invalid_socket) {dlg-> MessageBox ("Accept connection failed!"); Break; } IF (EventTotal> WSA_Maximum_Wait_Events) {DLG-> MessageBox ("Connection A number of overflows, refusal!"); Break;}

NEWEVENT = WSACREATEEVENT ();

IF (WSAEventSelect (ACCEPT, NewEvent, fd_read | fd_write | fd_close) == Socket_ERROR) {DLG-> MessageBox ("Register Network Event Failed!"); ClossoSocket (Accept); Break;}

Event [Eventtotal] = newevent; socket [Eventtotal] = Accept; EventTotal ;

IF (NetWorkevents.LnetWorkevents & fd_read) file: // Read data event {if (NetWorkevent.ierrorCode [fd_read_bit]! = 0) {DLG-> MessageBox ("Read Event Failed!"); Break;}

IF (DLG-> OnRecEive (socket [index - wsa_wait_event_0]) == false) {dlg-> messagebox ("Read Data Failed!"); Break;}}

IF (NetWorkevents.LNetworkEvents & fd_close) file: // Close the socket event {if (NetWorkevent.ierrorCode [fd_close_bit]! = 0) {dlg-> MessageBox ("Close Event Failed!"); Break;}

IF (DLG-> OnClose (socket [index - wsa_wait_event_0]) == false) {dlg-> MessageBox ("Close the socket failed!"); Break;}}} Return 0;}

BOOL CSERVERDLG :: OnClose (socket psocket) {INT I, EXITNUM; for (i = 0; i

M_ConnectNum -;

file: // send to all clients online customer information packets cmd_client_info ClientInfo; ClientInfo.cmd_type = CMD_CLIENT_INFO; ClientInfo.client_num = m_Connectnum; for (i = 0; i <= m_Connectnum; i ) {ClientInfo.Networks_ID [i] = m_ClientInfo [i] .Network_ID; strcpy (ClientInfo.users_name [i], m_ClientInfo [i] .User_Name); strcpy (ClientInfo.clients_ipaddr [i], inet_ntoa (m_ClientInfo [i] .Client_Addr.sin_addr));} for ( i = 0; i <= m_connectnum; i ) {send (m_clientinfo [i] .client_socket, (char *) & clientinfo, sizeof (cmd_client_info), null);} closesocket (psocket);

PLIST-> DeleteItem (Exitnum); Return True;

BOOL CServerDlg :: OnReceive (SOCKET pSocket) {static char rcvbuf [65535]; file: // buffer receiving int ret; int offset = 0; find_type * pFindType; int i = 0; CTime m_current_time = CTime :: GetCurrentTime () ; Cstring start_time = m_current_time.format ("% c"); cstring networkid; file: // Network ID item of the list box

RET = Recv (PSocket, RCVBUF, 65535, 0); if (RET == Operation_ERROR) RETURN FALSE;

while (offset cmd_type) {case CMD_HELLO: cmd_hello Hello; memcpy (& Hello, rcvbuf offset, sizeof (cmd_hello)); offset = sizeof (cmd_hello); cmd_hello_resp helloresp; m_networkid ; helloresp.cmd_type = cmd_hello_resp; helloresp.network_id = m_networkid; strcpy (hello.user_name);

memcpy ((struct sockaddr *) & (m_ClientInfo [m_Connectnum] .Client_Addr), (const struct sockaddr *) & clientaddr, sizeof (sockaddr)); m_ClientInfo [m_Connectnum] .Client_Socket = Accept; strcpy (m_ClientInfo [m_Connectnum] .User_Name, HelloResp .user_name); m_ClientInfo [m_Connectnum] .Network_ID = m_NetworkID; m_ClientInfo [m_Connectnum] .Login_Time = m_current_time; send (pSocket, (char *) & HelloResp, sizeof (cmd_hello_resp), NULL);

File: / / Send a response message SLEEP (200) to the logged in the client;

CMD_Client_info ClientInfo; ClientInfo.cmd_type = cmd_client_info; clientinfo.client_num = m_connectnum 1;

for (i = 0; i <= m_Connectnum; i ) {ClientInfo.Networks_ID [i] = m_ClientInfo [i] .Network_ID; strcpy (ClientInfo.users_name [i], m_ClientInfo [i] .User_Name); strcpy (ClientInfo.clients_ipaddr [I], INET_NTOA (m_clientinfo [i] .client_addr.sin_addr);}

File: // Send online client information packet for all online clients (i = 0; i <= m_connectnum; i ) {send (m_clientinfo [i] .client_socket, (char *) & clientinfo, sizeof (cmd_client_info), NULL }

File: // Refresh the client information list networkid.format ("% d", m_networkid);

LVITEM lvinsert; lvinsert.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; lvinsert.iItem = m_Connectnum; lvinsert.iSubItem = 0; lvinsert.cchTextMax = 20; lvinsert.pszText = HelloResp.user_name; lvinsert.iImage = 0; pList-> InsertItem ( & lvinsert); pList-> SetItemText (m_Connectnum, 1, networkid); pList-> SetItemText (m_Connectnum, 2, inet_ntoa (m_ClientInfo [m_Connectnum] .Client_Addr.sin_addr)); pList-> SetItemText (m_Connectnum, 3, strTime); m_Connectnum ;

break; case CMD_ASK: cmd_ask Ask; cmd_ask_resp AskResp; memcpy (& Ask, rcvbuf offset, sizeof (cmd_ask)); offset = sizeof (cmd_ask); AskResp.cmd_type = CMD_ASK_RESP; AskResp.Network_ID = Ask.Network_ID; for (i = 0; I

Break; Case CMD_Goodbye: CloseSocket; Break; Default: Break;}}

Return True;} Bool CServerdlg :: OnSend (socket psocket) {return true

Void CServerdlg :: Onok () {CloseSocket (M_Listensocket); wsacleanup (); cdialog :: onok ();

void CServerDlg :: OnTimer (UINT nIDEvent) {CTime m_current_time = CTime :: GetCurrentTime (); CTimeSpan logintimes; CString login_times; CString networkid; file: // network ID list box item for (int i = 0; i setItemtext (i, 4, login_times);} cdialog :: Ontimer (nidevent);

// ServerDlg.h: header file //

#if! defined (AFX_SERVERDLG_H__B0AA0367_C1F4_11D4_AB1C_0080C8D6FEA5__INCLUDED _) # Define AFX_SERVERDLG_H__B0AA0367_C1F4_11D4_AB1C_0080C8D6FEA5__included_

#if _MSC_VER> 1000 # prgma overce # endif //_MSC_VER> 1000

#include "global.h"

/// Cserververdlg Dialog

Class CServerdlg: Public CDialog {File: // Global Function Friend Uint KernelWorkthread (LPVOID PPARAM); // ConstructionPublic: ClistCtrl * PList; File: // Client Online Information list box Object CIMAGELIST M_IMAGELIST;

Socket M_Listensocket; file: // Used to listen to the port client_info m_clientinfo [max_client_num]; file: // Save the structure of the online client information SOCKADDR_IN ClientAddr; file: // Save the client address INT M_CONNECTNUM File: // Online client number int m_networkid; file: // Return to the client's network ID number

BOOL ONSEND (socket psocket); file: // Send a response function for data network event Bool OnRecEut (socket psocket); file: // Receive the response function of the data network event BOOL ONCLOSE (socket psocket); file: // Close the socket Response function for word network event

Cserververdlg (CWND * PParent = null); // Standard Constructionor

// Dialog Data file: // {{AFX_DATA (CSERVERDLG) ENUM {IDD = IDD_SERVER_DIALOG}; // Note: The classwizard will add data members here file: //}} AFX_DATA

// ClassWizard generated virtual function overrides file: // {{AFX_VIRTUAL (CServerDlg) protected: virtual void DoDataExchange (CDataExchange * pDX); // DDX / DDV support file: //}} AFX_VIRTUAL // Implementationprotected: HICON m_hIcon;

// Generated message map functions file: // {{AFX_MSG (CServerDlg) virtual BOOL OnInitDialog (); afx_msg void OnSysCommand (UINT nID, LPARAM lParam); afx_msg void OnPaint (); afx_msg HCURSOR OnQueryDragIcon (); virtual void OnOK () AFX_MSG Void ONTIMER (Uint NidEvent); File: //}} AFX_MSG DECLARE_MESSAGE_MAP ()};

File: // {{AFX_INSERT_LOCATION}} // Microsoft Visual C Will Insert Additional Declarations Immediately Before The Previous Line.

#ndif //! Defined (AFX_SERVERDLG_H__B0AA0367_C1F4_11D4_AB1C_0080C8D6FEA5__INCLUDED_)

转载请注明原文地址:https://www.9cbs.com/read-30474.html

New Post(0)