<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,comments - 227,trackbacks - 0
    根據(jù)前面一節(jié)的說明,服務端套接字應該按照如下順序建立:
    1. 初始化
    2. 創(chuàng)建套接字
    3. 綁定本地地址
    4. 進入偵聽狀態(tài)
    5. 處理接受循環(huán)

    下面首先創(chuàng)建一個例子來演示服務端套接字的實現(xiàn),并在以后的各節(jié)中優(yōu)化這個設計。

    這個設計實現(xiàn)的功能如下:允許客戶端(實際上就是telnet程序)登陸,并對客戶端的輸入回顯。

    4.1 準備工程

    為了實現(xiàn)這個demo,我打算使用Visual Studio 6.0提供的對話框模板來實現(xiàn),請按照下述步驟準備工程:

    1. 啟動Visual C++ 6.0
    2. 選擇File/New/Project
    3. 選擇MFC AppWizard(exe)
    4. 在Project name中輸入demo1, Next
    5. 選擇Dialog Base, Next
    6. 在Windows Sockets前打鉤
    7. 其他都保持缺省值,點擊Next完成向導
    8. 在工程中加入兩個文件:sockutil.h和sockutil.cpp:這兩個文件將保存公共的函數(shù),避免以后重復編寫。

    這樣創(chuàng)建的工程會自動加入WinSock2支持,具體的內(nèi)容包括:

    1. 在stdafx.h中加入#include <afxsock.h>,該頭文件包含如下語句載入對應LIB:
      #pragma comment(lib, "wsock32.lib")
    2. 在InitInstance中加入如下代碼:
      if(!AfxSocketInit())
      {
      AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
      return FALSE;
      }
    3. 在資源中定義字符串資源IDP_SOCKETS_INIT_FAILED:Windows通訊端口初始化失敗

    如果大家創(chuàng)建工程時沒有加入對應的sock支持,我們可以參照上述列表手工加入。

    對于前文所述的sockutil.h文件,加入如下初始代碼:

    #if !defined(__SOCKET_UTILITY_HEADER__)
    #define __SOCKET_UTILITY_HEADER__
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    #endif

    對于sockutil.cpp文件,則加入如下初始代碼:

    #include "stdafx.h"
    #include "sockutil.h"
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    4.2 準備錯誤處理方式

    在編制每個程序之前,我習慣是為錯誤處理定制一個統(tǒng)一的處理方式。在以后的例子中,我會按照如下的方式處理錯誤:在一個log文件中記錄錯誤發(fā)生的位置(文件、行號),錯誤號和字符串解釋。為了實現(xiàn)這個目的,我在sockutil.cpp定義如下的函數(shù):

    bool ErrorHandle(LPCTSTR expression, bool bFalse, LPCTSTR file, UINT line)
    {
    if(!bFalse)
    {//沒有錯誤,直接返回
    return false;
    }
    FILE * fp;
    fp = fopen("demo.log","at");
    if(NULL == fp)
    {//如果文件打開失敗,放棄記錄
    return true;
    }
    //獲得錯誤碼
    DWORD ErrorCode = GetLastError();
    //格式化成字符串格式
    LPVOID lpMsgBuf;
    FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM |
    FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    ErrorCode ,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR) &lpMsgBuf,
    0,
    NULL
    );
    //輸出到文件
    fprintf(fp,_T("file=%s,line=%u"n%d:%s"n"),file,line,ErrorCode, (LPCTSTR)lpMsgBuf);
    // 釋放空間,該空間由FormatMessage分配
    LocalFree( lpMsgBuf );
    //關閉文件
    fclose(fp);

    return true;
    }

    在sockutil.h中,添加如下代碼:

    bool ErrorHandle(LPCTSTR expression, bool bFalse, LPCTSTR file, UINT line);
    #define ERRORHANDLE(expression) ErrorHandle(#expression,(expression),__FILE__,__LINE__)

    4.3 核心代碼

    根據(jù)前文,設計該服務端套接字主函數(shù)如下:

    void sockmain(LPCTSTR ip, UINT port)
    {

    SOCKET hSocket;
    hSocket = socket(AF_INET,SOCK_STREAM,0);
    if(ERRORHANDLE(hSocket == INVALID_SOCKET))
    {
    return;
    }
    sockaddr_in addr;
    InitializeAddress(inet_addr(ip), port, addr);
    if(ERRORHANDLE(SOCKET_ERROR == bind(hSocket, (const sockaddr*) & addr, sizeof(addr))))
    {
    closesocket(hSocket);
    return;
    }
    if(ERRORHANDLE(SOCKET_ERROR == listen(hSocket,5)))
    {
    closesocket(hSocket);
    return;
    }
    SOCKET hClient;
    int size;
    char buffer[2048];
    int length;
    size = sizeof(addr);
    while(INVALID_SOCKET != (hClient = accept(hSocket,(sockaddr*)&addr, & size)))
    {
    size = sizeof(addr);
    while((length = recv(hClient, buffer, sizeof(buffer),0)) > 0)
    {
    SendData(hClient,buffer, length);
    }
    closesocket(hClient);
    }
    closesocket(hSocket);

    return;
    }

    其中,InitializeAddress定義如下:

    void InitializeAddress(DWORD ip, UINT port, sockaddr_in & addr)
    {
    memset(&addr,0,sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr= ip;
    addr.sin_port = htons(port);
    }
    SendData定義如下:
    int SendData(SOCKET hSocket, const char * data, int length)
    {
    int result;
    int pos = 0;
    while(pos < length)
    {
    result = send(hSocket, data + pos, length - pos , 0);
    if(result > 0 )
    {
    pos += result;
    }else{
    return result;
    }
    }
    return length;
    }

    4.4 啟動該任務

    為了啟動服務端套接字,我們可以在對話框資源的OK按鈕上雙擊,然后在OnOK中添加如下代碼

       sockmain("0.0.0.0",2000);

    當我們啟動該工程,并點擊OK按鈕,就可以通過telnet來測試是否有回顯功能了。

    posted on 2008-07-03 15:19 SIMONE 閱讀(636) 評論(0)  編輯  收藏 所屬分類: C++
    主站蜘蛛池模板: 中文亚洲AV片在线观看不卡 | 久久亚洲伊人中字综合精品| 国产AV日韩A∨亚洲AV电影| 免费观看一级毛片| 国产精品亚洲精品久久精品| 日美韩电影免费看| 亚洲av综合av一区二区三区| 国产免费资源高清小视频在线观看| 亚洲高清一区二区三区电影| 国产人成免费视频| 五级黄18以上免费看| 久久久久亚洲AV成人片| 97公开免费视频| 亚洲国产av美女网站| 国内外成人免费视频| 99亚洲男女激情在线观看| 亚洲免费日韩无码系列| 野花香在线视频免费观看大全 | 亚洲成a人片毛片在线| 亚洲第一成年免费网站| 大桥未久亚洲无av码在线| 亚洲日本一区二区三区在线不卡| 免费看又黄又爽又猛的视频软件| 久久精品国产精品亚洲精品| 久久九九兔免费精品6| 亚洲AV日韩AV永久无码色欲| 亚洲另类少妇17p| 久久久久久夜精品精品免费啦| 亚洲制服丝袜中文字幕| 免费人成在线观看视频播放| 国产婷婷成人久久Av免费高清| 亚洲依依成人精品| 亚洲VA综合VA国产产VA中| 久久久久国产精品免费免费不卡| 国产精品久久亚洲不卡动漫| 亚洲精品无码av天堂| 成人免费视频69| 国产精品免费久久久久电影网| 亚洲乱码一二三四区乱码| 国产黄色一级毛片亚洲黄片大全| 在线日本高清免费不卡|