• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 29,comments - 10,trackbacks - 0

            今天學(xué)習(xí)了些關(guān)于VC網(wǎng)絡(luò)編程中關(guān)于Winsock的知識,并做了相應(yīng)的整理。在這里根據(jù)了一個(gè)聊天室例子幫助我了解這些知識的用法。
            (1)Server端調(diào)用函數(shù)順序:
                     WSAStartup()初始化Winsock
                     socket()創(chuàng)建一個(gè)監(jiān)聽Socket
                     bind()為監(jiān)聽Socket指定通信對象
                     listen()設(shè)置等待連接狀態(tài)
                     accept()接收連接并生成會話Socket
                     send和recv進(jìn)行對話
                     closesocket()關(guān)閉socket
            (2)Client端調(diào)用函數(shù)順序
                     WSAStartup()初始化Winsock
                     socket()創(chuàng)建一個(gè)監(jiān)聽Socket
                     connect()與Server端連接
                     send和recv進(jìn)行對話
                     closesocket()關(guān)閉socket
            1、程序頭部分,包括引用的頭文件、宏定義、全局變量和函數(shù)聲明

            #include "stdafx.h"
            #include 
            "resource.h"
            #include 
            <VECTOR>                        //采用STL
            #include <algorithm>
            #include 
            <WINSOCK2.H>                    //調(diào)用winsock                        
            #include <ASSERT.H>

            #define BUFFER_SIZE 4096               //緩沖區(qū)的大小
            #define SERVER_MESSAGE WM_USER+100        //服務(wù)器SOCKET異步消息ID
            #define CLIENT_MESSAGE WM_USER+101      //客戶機(jī)SOCKET異步消息ID

            // Global Variables:
            SOCKET g_ListenSocket;                //Listen socket (for server)
            std::vector<SOCKET>  g_DataSockets;    //All data sockets with clients (for server)
            SOCKET g_ClientSocket;                //Client data socket (for client)
            BOOL g_bActive;                        //A tag of active socket (for both server and client)
            std::string g_ChatWords;
            BOOL g_bClient;                        
            //TRUE as a client, FALSE as a server

            BOOL ServerInit(HWND hWnd,UINT port);
            BOOL ClientInit(HWND hWnd,UINT port,
            const char* serverIP);
            int OnClientMessage(HWND hWnd, WPARAM wParam, LPARAM lParam);
            int OnServerMessage(HWND hWnd, WPARAM wParam, LPARAM lParam);
            void SendMessageToPeer(HWND hWnd);
            void Send(SOCKET sock, const char* buffer, int length);
            void RefreshScreen(HWND hWnd);
            void ExitChat(HWND hWnd);
            void GetErrorReason();
            2、Win32程序函數(shù)入口點(diǎn)WinMain:
            LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
            int APIENTRY WinMain(HINSTANCE hInstance,
                                 HINSTANCE hPrevInstance,
                                 LPSTR     lpCmdLine,
                                 
            int       nCmdShow)
            {
                
            // Perform application initialization:
                g_bActive=FALSE;
                DialogBox(hInstance, MAKEINTRESOURCE(IDD_CHAT_DIALOG), NULL, (DLGPROC)WndProc);
                
            return 0;
            }
            3、對話框的消息循環(huán)函數(shù)WndProc:
                  WndProc消息循環(huán)中,只處理4中消息:對話框初始化、對話框控件、服務(wù)器SOCKET異步和客戶端SOCKET異步,在對話框初始化中,程序啟動了SOCKET棧。在對話框控件中,程序分別響應(yīng)了各種按鈕消息以及文字輸入框消息EN_UPDATE。在服務(wù)器SOCKET異步消息中,調(diào)用OnServerMessage處理。在客戶端SOCKET異步消息中,調(diào)用了OnclientMessage處理。
            LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
            {
                HWND subWnd;
                
            char buffer[BUFFER_SIZE];
                UINT port;
                
            char serverIP[16];
                
            switch (message)
                
            {
                
            case WM_INITDIALOG:
                    
            {
                        WSADATA wsaData;
                        
            if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
                        
            {
                            MessageBox(hWnd,
            "Socket Stack Error!","Error",IDOK);
                            
            return -1;
                        }

                    }

                    
            return TRUE;
                
            case WM_COMMAND:
                    
            {
                        
            switch(LOWORD(wParam))
                        
            {
                        
            case IDOK:
                        
            case IDCANCEL:
                            EndDialog(hWnd,LOWORD(wParam));
                            
            break;
                        
            case IDC_CONNECT:
                            
            {
                                subWnd
            =GetDlgItem(hWnd,IDC_LISTEN_PORT_C);
                                GetWindowText(subWnd,buffer, BUFFER_SIZE);
                                port
            = UINT(atoi(buffer));
                                subWnd
            =GetDlgItem(hWnd,IDC_SERVERIP);
                                GetWindowText(subWnd,buffer,BUFFER_SIZE);
                                strncpy(serverIP,buffer,
            16);
                                ClientInit(hWnd,port,serverIP);
                                
            //g_ChatWords="";
                            }

                            
            break;
                        
            case IDC_LISTEN:
                            
            {
                                subWnd
            =GetDlgItem(hWnd,IDC_LISTEN_PORT_S);
                                GetWindowText(subWnd,buffer, BUFFER_SIZE);
                                port
            = UINT(atoi(buffer));
                                ServerInit(hWnd,port);
                                
            //g_ChatWords="";
                            }

                            
            break;
                        
            case IDC_INPUTTEXT:
                            
            {
                                
            if(HIWORD(wParam)==EN_UPDATE)
                                
            {
                                    SendMessageToPeer(hWnd);
                                }

                            }

                        
            default:
                            
            break;
                        }

                    }

                    
            break;
                
            case SERVER_MESSAGE:
                    
            {
                        OnServerMessage(hWnd,wParam, lParam);
                    }

                    
            break;
                
            case CLIENT_MESSAGE:
                    
            {
                        OnClientMessage(hWnd, wParam, lParam);
                    }

                    
            break;
                }

                
            return 0;
            }

            1)int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);
                  
            wVersionRequested:表示欲使用的Windows Sockets API版本,使用宏MAKEWORDXY)設(shè)置參數(shù)。表示版本為X.Y(本例中為2.2)
            4、客戶端初始化函數(shù)ClientInit:

               當(dāng)單擊“連接服務(wù)器“按鈕時(shí),程序分別從子窗口IDC_LISTEN_POST_CIDC_SERVERIP中提取服務(wù)器的IP和監(jiān)聽端口,然后調(diào)用客戶端函數(shù)ClientInit

            BOOL ClientInit(HWND hWnd,UINT port,const char* serverIP)
            {
                sockaddr_in addr;
                ExitChat(hWnd);
                g_bClient
            =TRUE;
                
            if(inet_addr(serverIP)==INADDR_NONE)
                
            {
                    MessageBox(hWnd,
            "Invalid IP Address!","Warnning",IDOK);
                    
            return FALSE;
                }


                
            //create tcp/stream data socket
                g_ClientSocket = socket(AF_INET, SOCK_STREAM,0);
                assert(g_ClientSocket 
            != INVALID_SOCKET);

                
            //set the socket as async selection tag, the related message is CLIENT_MESSAGE
                
            //the async events contain: read, write, close, connect
                WSAAsyncSelect(g_ClientSocket,hWnd,CLIENT_MESSAGE,FD_READ|FD_WRITE|FD_CLOSE|FD_CONNECT);

                
            //set the server address and port
                addr.sin_family = AF_INET;
                addr.sin_addr.S_un.S_addr 
            = inet_addr(serverIP);
                addr.sin_port 
            = htons(port);   //short from host to network format
                
                
            //connect to server
                connect(g_ClientSocket, (sockaddr*)&addr, sizeof(addr));

                g_ChatWords
            +="Connecting\r\n";
                RefreshScreen(hWnd);
                
            return TRUE;
            }

            1SOCKET socket(int af,int type,int protocol);

                   af:指協(xié)議的地址族,如果想建立一個(gè)UDPTCP的套接字,則該值設(shè)置成AF_INET,表示在網(wǎng)絡(luò)層采用網(wǎng)際協(xié)議(IP

                   type:協(xié)議的套接字類型,可以是SOCK_STREAMSOCK_DGRAM SOCK_RAWSOCK_RDMSOCK_SEQPACKET 當(dāng)采用流連接方式時(shí)用SOCK_STREAM,采用數(shù)據(jù)報(bào)文方式用SOCK_DGRAM

                   proctocol:協(xié)議字段,當(dāng)aftype都指定之后,該值的取值范圍就被去定了,默認(rèn)值為0

            2int PASCAL FAR WSAAsyncSelect ( SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent );

            S:標(biāo)識一個(gè)需要事件通知的套接口的描述符.

            hWnd:標(biāo)識一個(gè)在網(wǎng)絡(luò)事件發(fā)生時(shí)需要接收消息的窗口句柄.

            wMsg :在網(wǎng)絡(luò)事件發(fā)生時(shí)要接收的消息.

            lEvent:位屏蔽碼,用于指明應(yīng)用程序感興趣的網(wǎng)絡(luò)事件集合.

            3int connect(SOCKET s,const struct sockaddr FAR * name,int namelen);

                   S是建立好的套接字,name指向描述通信對象地址信息的結(jié)構(gòu)體的指針,namelen是該結(jié)構(gòu)體的長度。

            4struct sockaddr_in {short sin_family;u_short sin_port;struct in_addr sin_addr;char    sin_zero[8];};

            5unsigned long PASCAL FAR inet_addr( const struct FAR* cp);

              cp:一個(gè)以Internet標(biāo)準(zhǔn)“.”間隔的字符串。

            本函數(shù)解釋cp參數(shù)中的字符串,這個(gè)字符串用Internet“.”間隔格式表示一個(gè)數(shù)字的Internet地址。

            6u_short PASCAL FAR htons( u_short hostshort);

              hostshort:主機(jī)字節(jié)順序表達(dá)的16位數(shù)。

              本函數(shù)將一個(gè)16位數(shù)從主機(jī)字節(jié)順序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序。

                   其中sin_family是指地址族;sin_port是制定的端口號;sin_addr是制定的IP地址;sin_zero冗余字段,使sockaddr_in結(jié)構(gòu)和SOCKADDR結(jié)構(gòu)大小相同
            5、服務(wù)器初始化函數(shù)ServerInit:
               單擊“建立服務(wù)器“按鈕時(shí),程序從子窗口IDC_LISTEN_PORT_S中提取監(jiān)聽端口,然后調(diào)用服務(wù)器初始化函數(shù)ServerInit

            BOOL ServerInit(HWND hWnd,UINT port)
            {
                sockaddr_in addr;
                
            char buffer[BUFFER_SIZE];
                ExitChat(hWnd);
                g_bClient
            =FALSE;
                
                
            //create a tcp/stream based socket
                g_ListenSocket = socket(AF_INET, SOCK_STREAM,0);
                assert(g_ListenSocket 
            != INVALID_SOCKET);

                
            //set the socket as async selection tag, the related message is SERVER_MESSAGE
                
            //the async events contain: accept, read, write, close
                WSAAsyncSelect(g_ListenSocket, hWnd, SERVER_MESSAGE, FD_ACCEPT|FD_READ|FD_WRITE|FD_CLOSE);

                addr.sin_family 
            = AF_INET;  //IP layer takes IP router protocol
                addr.sin_addr.S_un.S_addr = INADDR_ANY;    
                addr.sin_port 
            = htons(port);//port from short of host to short of network

                
            //binding listening socket
                if(bind(g_ListenSocket, (sockaddr*)&addr, sizeof(sockaddr)) == SOCKET_ERROR)
                
            {
                    sprintf(buffer,
            "Port %d has been taken. Change another port.\r\n",port);
                    g_ChatWords
            +=buffer;
                    RefreshScreen(hWnd);
                    MessageBox(hWnd,
            "Binding Error","Warnning",IDOK);
                    
            return FALSE;
                }

                
                
            //listening
                if(listen(g_ListenSocket, 5== SOCKET_ERROR)
                
            {
                    strcpy(buffer,
            "Listen error.\r\n");
                    g_ChatWords
            +=buffer;
                    RefreshScreen(hWnd);
                    MessageBox(hWnd,
            "Listen Error.","Warnning",IDOK);
                    
            return FALSE;
                }


                g_ChatWords
            +="Server is listening\r\n";
                RefreshScreen(hWnd);
                g_bActive
            =TRUE;
                
            return TRUE;
            }

            1)  int bind(SOCKET s,const struct sockaddr FAR * name,int namelen);

            S是建立好的套接字,name指向描述通信對象地址信息的結(jié)構(gòu)體的指針,namelen是該結(jié)構(gòu)體的長度。

            2)int listen(SOCKET s,int backlog);

            S是建立好的套接字,backlog是并發(fā)連接等待隊(duì)列的長度。

            6、SendMessageToPeer函數(shù):
               當(dāng)用戶在文本框中輸入文字時(shí),程序會接收到該文本框的
            EN_UPDATE消息,函數(shù)SendMessageToPeer負(fù)責(zé)處理該消息。在SendMessageToPeer中,一旦檢測到用戶按下了回車鍵,程序就將文本內(nèi)容刷新到上面的顯示框中,如果當(dāng)前在線,文本內(nèi)容還將發(fā)送到會話的另一端。

            void SendMessageToPeer(HWND hWnd)
            {
                HWND subwnd;
                
            char buffer[BUFFER_SIZE];
                
            int i;
                
            static int oldNumOfChars=0;

                subwnd
            =GetDlgItem(hWnd,IDC_INPUTTEXT);
                GetWindowText(subwnd,buffer,BUFFER_SIZE
            -2);
                
            if(oldNumOfChars!=strlen(buffer))
                
            {
                    oldNumOfChars
            =strlen(buffer);
                    
            return;
                }

                
            //CString s;
                
            //s("%d還是%d",oldNumOfChars,strlen(buffer));
            //    g_ChatWords+=s;
                
            //empty content of input edit box
                SetWindowText(subwnd,"");
                oldNumOfChars
            =0;
                
            if(!g_bActive)
                
            {
                    g_ChatWords
            +=buffer;
                    g_ChatWords.erase(g_ChatWords.size(),
            1);
                    g_ChatWords
            +="(Hint: you are isolated now.)\r\n";
                    RefreshScreen(hWnd);
                    
            return;
                }

                strcat(buffer,
            "\r\n");
                g_ChatWords
            +=buffer;
                RefreshScreen(hWnd);
                
            if(g_bClient)
                
            {
                    Send(g_ClientSocket, buffer, strlen(buffer));
                }

                
            else
                
            {
                    
            for(i=0;i<g_DataSockets.size();i++)
                        Send(g_DataSockets[i],buffer,strlen(buffer));
                }

            }

            void Send(SOCKET sock, const char* buffer, int length)
            {
                
            int ret,i;
                i
            =0;
                
            while(length>0)
                
            {
                    ret
            =send(sock,&(buffer[i]),length,0);
                    
            if(ret==0)
                        
            break;
                    
            else if(ret == SOCKET_ERROR)
                    
            {
                        g_ChatWords
            +="Error sending.\r\n";
                        
            break;
                    }

                    length
            -=ret;
                    i
            +=ret;
                }

            }

            1)int send(SOCKET s,const char FAR * buf,int len,int flags);
            參數(shù)s是建立連接的套接字。buflen是發(fā)送的數(shù)據(jù)包及其長度。flags一般取0,還有MSG_DONTROUTE要求套接字傳輸?shù)臄?shù)據(jù)不要路由,如果傳輸協(xié)議不支持該選項(xiàng),則這個(gè)要求被忽略。MSG_OOB表示套接字此時(shí)傳輸?shù)臄?shù)據(jù)室外帶數(shù)據(jù),需要緊急處理。

            7、OnClientMessage函數(shù):

            在主循環(huán)的消息循環(huán)中,OnClientMessage函數(shù)用來處理客戶端SOCKET的一部消息CLIENT_MESSAGE。需要指出的是:當(dāng)某個(gè)網(wǎng)絡(luò)消息到達(dá)窗口時(shí),可能暗含著套接字上發(fā)生了某種網(wǎng)絡(luò)錯(cuò)誤。此時(shí),應(yīng)該先判斷套接字上是否發(fā)生了錯(cuò)誤,如果有錯(cuò)誤發(fā)生就直接關(guān)閉套接字然后返回,只有在沒有錯(cuò)誤發(fā)生的情況下,才需要處理具體的網(wǎng)絡(luò)消息。在實(shí)現(xiàn)上,需要利用消息參數(shù)lParam的高字節(jié),宏WSAGETSELECTERROR可以檢測錯(cuò)誤。而具體的消息類型是存儲在lParam的低字節(jié),宏WSAGETSELECTEVENT用來獲取該低字節(jié)值。

            int OnClientMessage(HWND hWnd, WPARAM wParam, LPARAM lParam)
            {
                
            char buffer[BUFFER_SIZE+1];
                
            int retCode;
                sockaddr_in name;
                
            int namelen=sizeof(sockaddr_in);

                
            if(WSAGETSELECTERROR(lParam))
                
            {
                    closesocket(g_ClientSocket);
                    strcpy(buffer,
            "Server has no response.\r\n");
                    g_ChatWords
            +=buffer;
                    RefreshScreen(hWnd);
                    g_bActive
            =FALSE;
                    
            return 0;
                }


                
            switch(WSAGETSELECTEVENT(lParam))
                
            {
                    
            case FD_CONNECT:
                        getpeername(g_ClientSocket,(sockaddr
            *)&name,&namelen);
                        sprintf(buffer,
            "Successfully connected to %s:%d.\r\n",inet_ntoa(name.sin_addr),ntohs(name.sin_port));
                        g_ChatWords
            +=buffer;
                        RefreshScreen(hWnd);
                        g_bActive
            =TRUE;
                        
            break;
                    
            case FD_READ:
                        retCode
            =recv(g_ClientSocket,buffer,BUFFER_SIZE,0);
                        
            if(retCode!=SOCKET_ERROR)
                        
            {
                            buffer[retCode]
            =NULL;
                            g_ChatWords
            +=buffer;
                        }

                        
            else
                            GetErrorReason();
                        RefreshScreen(hWnd);
                        
            break;
                    
            case FD_WRITE:
                        
            break;
                    
            case FD_CLOSE:
                        closesocket(g_ClientSocket);
                        strcpy(buffer,
            "Server close session.Successfully log out.\r\n");
                        g_ChatWords
            +=buffer;
                        RefreshScreen(hWnd);
                        g_bActive
            =FALSE;
                        
            break;
                }

                
            return 0;
            }

            1char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
                  in:一個(gè)表示Internet主機(jī)地址的結(jié)構(gòu)。
               
            本函數(shù)將一個(gè)用in參數(shù)所表示的Internet地址結(jié)構(gòu)轉(zhuǎn)換成以“.” 間隔的諸如“a.b.c.d”的字符串形式。

            2) int recv(SOCKET s,char FAR * buf,int len,int flags);
            參數(shù)與send一致

            3)int closesocket(SOCKET s);
            關(guān)閉套接字

            8、OnServerMessage函數(shù):

            在主程序的消息循環(huán)中,OnServerMessage函數(shù)用來處理客戶端SOCKET的一部消息SERVER_MESSAGE。在服務(wù)器初始化函數(shù)中的g_ListenSocket被設(shè)置成異步監(jiān)聽socket,所有被g_ListenSocket接收的數(shù)據(jù)socket將同時(shí)被設(shè)置成異步socket,并共享同一個(gè)消息SERVER_MESSAGE。及時(shí)服務(wù)器關(guān)閉了監(jiān)聽socket,會話socket的連接依然有效,除非服務(wù)器同時(shí)也將會話socket關(guān)閉。

            int OnServerMessage(HWND hWnd, WPARAM wParam, LPARAM lParam)
            {
                SOCKET socket;
                
            int i,retCode,namelen;
                
            char buffer[BUFFER_SIZE+1];
                std::vector
            <SOCKET>::iterator ite;
                sockaddr_in name;
                namelen
            =sizeof(name);

                
            if(WSAGETSELECTERROR(lParam))
                
            {
                    getpeername((SOCKET)wParam,(sockaddr
            *)&name,&namelen);
                    closesocket((SOCKET)wParam);
                    
            //erase the client socket from client socks list
                    ite=std::find(g_DataSockets.begin(), g_DataSockets.end(),(SOCKET)wParam);
                    assert(ite
            !=g_DataSockets.end());
                    g_DataSockets.erase(ite);
                    
            //refresh screen
                    sprintf(buffer, "Client %s:%d lost contact with us.\r\n", inet_ntoa(name.sin_addr),ntohs(name.sin_port));
                    
            for(i=0; i<g_DataSockets.size(); i++)
                        Send(g_DataSockets[i],buffer,strlen(buffer));
                    g_ChatWords
            +=buffer;
                    RefreshScreen(hWnd);
                    
            return 0;
                }


                
            switch(WSAGETSELECTEVENT(lParam))
                
            {
                    
            case FD_ACCEPT:
                        
            //accept the client request
                        socket= accept(g_ListenSocket,NULL,NULL);
                        
            //in fact we can get the peer when calling accept, here we use getpeername instead
                        getpeername(socket,(sockaddr*)&name,&namelen);
                        
            //send a message of logining to other clients
                        sprintf(buffer,"A guest joins us.(%s:%d)\r\n",inet_ntoa(name.sin_addr),ntohs(name.sin_port));
                        g_ChatWords
            +=buffer;
                        
            for(i=0;i<g_DataSockets.size();i++)
                            Send(g_DataSockets[i],buffer,strlen(buffer));
                        
            //send a welcome message to current client
                        sprintf(buffer, "Welcome !(You ID is: %s:%d.)\r\n",inet_ntoa(name.sin_addr),ntohs(name.sin_port));
                        
            //send(socket,buffer,strlen(buffer),0);
                        Send(socket,buffer,strlen(buffer));
                        
            //refresh srceen text
                        RefreshScreen(hWnd);
                        
            //push the client socket down to the client sockets list
                        g_DataSockets.push_back(socket);
                        
            break;
                    
            case FD_READ:
                        
            {
                            
            //get the client message, the client socket ID is wParam
                            retCode=recv((SOCKET)wParam,buffer,BUFFER_SIZE,0);
                            buffer[retCode]
            =NULL;
                            
            //send the received message to other clients
                            for(i=0;i<g_DataSockets.size();i++)
                            
            {
                                
            if(wParam!=g_DataSockets[i])
                                    Send(g_DataSockets[i],buffer,strlen(buffer));
                            }

                            g_ChatWords
            +=buffer;
                            
            //refresh screen
                            RefreshScreen(hWnd);
                        }

                        
            break;
                    
            case FD_WRITE:
                        
            return 0;
                    
            case FD_CLOSE: //Client gracefully close the socket
                        
            //close the client socket who has left, the client socket ID is wParam
                        getpeername((SOCKET)wParam,(sockaddr*)&name,&namelen);
                        closesocket((SOCKET)wParam);
                        
            //erase the client socket from client socks list
                        ite=std::find(g_DataSockets.begin(), g_DataSockets.end(),(SOCKET)wParam);
                        assert(ite
            !=g_DataSockets.end());
                        g_DataSockets.erase(ite);
                        
            //refresh screen
                        sprintf(buffer, "Client %s:%d left.\r\n", inet_ntoa(name.sin_addr),ntohs(name.sin_port));
                        
            for(i=0; i<g_DataSockets.size(); i++)
                            Send(g_DataSockets[i],buffer,strlen(buffer));
                        g_ChatWords
            +=buffer;
                        RefreshScreen(hWnd);
                        
            break;
                }

                
            return 0;
            }

            1int PASCAL FAR getpeername( SOCKET s, struct sockaddr FAR* name,int FAR* namelen);

              s:標(biāo)識一已連接套接口的描述字。

              name:接收端地址的名字結(jié)構(gòu)。

            namelen:一個(gè)指向名字結(jié)構(gòu)的指針。

            2u_short PASCAL FAR ntohs( u_short netshort);

            netshort:一個(gè)以網(wǎng)絡(luò)字節(jié)順序表達(dá)的16位數(shù)。

            本函數(shù)將一個(gè)16位數(shù)由網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為主機(jī)字節(jié)順序。

            3) SOCKET accept(SOCKET s,struct sockaddr FAR * addr,int FAR * addrlen);

            如果是服務(wù)器并不關(guān)心對方的地址,則可將accept函數(shù)中后兩個(gè)參數(shù)設(shè)置為NULL

            9、最后,介紹3個(gè)輔助函數(shù):ExitChat、GetErrorReason和RefreshScreen
                  當(dāng)新建服務(wù)器或鏈接服務(wù)器的時(shí)候,首先需要將上一次會話關(guān)閉,ExitChat函數(shù)完成此功能。
                  RefreshScreen函數(shù)負(fù)責(zé)刷新顯示內(nèi)容并滾動顯示文本框。
                  GetErrorReason函數(shù)負(fù)責(zé)獲得當(dāng)前操作中的具體錯(cuò)誤原因。
            void ExitChat(HWND hWnd)
            {
                
            int i;
                
            char buffer[BUFFER_SIZE];
                
            if(g_bActive)
                
            {
                    
            if(g_bClient)
                    
            {
                        closesocket(g_ClientSocket);
                        strcpy(buffer,
            "Successfully log out.\r\n");
                        g_ChatWords
            +=buffer;
                        RefreshScreen(hWnd);
                    }

                    
            else
                    
            {
                        strcpy(buffer,
            "I will leave. Pls clients log out ASAP.\r\n");
                        
            for(i=0; i<g_DataSockets.size(); i++)
                        
            {
                            Send(g_DataSockets[i],buffer,strlen(buffer));
                            closesocket(g_DataSockets[i]);
                        }

                        g_DataSockets.clear();
                        
                        closesocket(g_ListenSocket);
                        strcpy(buffer,
            "Successfully close server.\r\n");
                        g_ChatWords
            +=buffer;
                        RefreshScreen(hWnd);
                    }

                }

                g_bActive
            =FALSE;
            }


            void GetErrorReason()
            {
                LPVOID lpMsgBuf;
                FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
            |FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
                    NULL,WSAGetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) 
            &lpMsgBuf,0,NULL);
                g_ChatWords
            +=(char *)lpMsgBuf;
                LocalFree( lpMsgBuf );
            }

            void RefreshScreen(HWND hWnd)
            {
                HWND subWnd;
                std::
            string::size_type pos;
                
            int n;
                subWnd
            =GetDlgItem(hWnd,IDC_SHOWTEXT);
                SetWindowText(subWnd, g_ChatWords.c_str());
                n
            =0;
                pos
            =0;
                
            while((pos=g_ChatWords.find('\n',pos))!=std::string::npos)
                
            {
                    pos
            ++;
                    n
            ++;
                }

                SendMessage(subWnd, EM_LINESCROLL, 
            0, n);
            }

            posted on 2009-06-21 00:23 The_Moment 閱讀(1937) 評論(0)  編輯 收藏 引用 所屬分類: VC理論
            麻豆久久| 久久精品成人免费观看97| 久久SE精品一区二区| 色综合久久久久无码专区| 久久久噜噜噜久久中文福利| 久久er国产精品免费观看2| 亚洲午夜无码AV毛片久久| 久久99国产亚洲高清观看首页| 久久99精品国产一区二区三区 | 婷婷综合久久中文字幕| 亚洲精品乱码久久久久久蜜桃| 久久久久久午夜成人影院| 中文字幕成人精品久久不卡| 国产一区二区久久久| 亚洲第一永久AV网站久久精品男人的天堂AV| 综合久久一区二区三区| 精品免费久久久久国产一区| 久久婷婷综合中文字幕| 97久久精品无码一区二区| 久久久无码精品亚洲日韩蜜臀浪潮| 狼狼综合久久久久综合网| 久久午夜夜伦鲁鲁片免费无码影视 | 久久伊人精品青青草原高清| 久久久九九有精品国产| 91精品国产91热久久久久福利 | 伊人久久综合成人网| 国产精品久久久久AV福利动漫| 久久久久国产一区二区| 亚洲AV日韩AV天堂久久| 久久精品国产影库免费看| 久久精品国产精品亚洲精品| 久久99精品久久久久子伦| 久久er国产精品免费观看2| 久久97久久97精品免视看秋霞 | 国产综合成人久久大片91| 久久久久久精品无码人妻| 九九久久99综合一区二区| 久久精品中文字幕有码| 精品久久久中文字幕人妻| 很黄很污的网站久久mimi色| 亚洲狠狠婷婷综合久久久久|