Winsock編程_第1篇_TCP套接字編程

      最近受一位編程牛人的影響,本身決定從今天開始將Windows Sockets 網絡編程的內容以日誌的形式記錄下來,其一是爲本身保留一份筆記,其二是加深本身對winsock編程的理解,其三是和喜歡代碼的朋友一塊兒分享編程的樂趣,我不知道本身能不能一直堅持下去,可是我會盡本身最大的努力作到每週更新1-2篇,在此也但願更多的朋友爲我提出建議,若是你也喜歡編程,在閱讀代碼的過程當中有什麼疑問,請與本人進行探討。
        每次我會以一段程序代碼的分析來闡述其中的知識點,由於閱讀大量優秀代碼能夠快速提高自身的編程水平。

      首先介紹下計算機通訊系統互聯參考模型OSI (Open System Interconnection) 編程


這就是OSI模型,重最底部的物理層開始到最頂部的應用層結束,該模型的7層完整結構闡述了基本的網絡概念。具體內容可查閱百度。

TCP/IP模型分爲四層結構: 服務器


應用層:至關於OSI模型的上面三層,包括各類應用程序和協議,協議有HTTP,FTP等等
傳輸層:包括TCP、UDP協議
網絡層:IP、ARP、RARP、ICMP協議
數據鏈路層:至關於OSI模型的下面兩層,通俗點說這一層就是網卡驅動和網卡物理設備。
sockets編程發生在應用層和傳輸層之間。
 接下來以一個簡單的TCP通訊程序做爲示例:
編譯器Visual Stdio 2012,實現代碼C++。
 Server Code:
網絡

// Server.cpp : 定義控制檯應用程序的入口點。
//
#include "stdafx.h"
#include "winsock2.h"
#define  BUF_SZIE     64
#pragma comment(lib, "ws2_32.lib")

int main(int argc, char* argv[])
{
    WSADATA            wsad;            //WSADATA變量
    SOCKET            Server;        //服務器套接字
    SOCKET            Client;        //客戶端套接字
    SOCKADDR_IN        addrServ;        //服務器地址
    char            buf[BUF_SZIE];        //接收數據緩衝區
    int                retVal;        //返回值

    //初始化套接字動態庫
    if (WSAStartup(MAKEWORD(2,2),&wsad) != 0)
    {
        printf("初始化套接字動態庫失敗!\n");
        return 1;
    }
    
    //建立套接字
    Server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    
    if(INVALID_SOCKET == Server)
    {
        printf("建立套接字失敗!\n");
        WSACleanup();//釋放套接字資源;
        return  -1;
    }
    
    //服務器套接字地址 
    addrServ.sin_family = AF_INET;
    addrServ.sin_port = htons(2012);
    addrServ.sin_addr.s_addr = INADDR_ANY;        
    //綁定套接字
    retVal = bind(Server, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));
    if(SOCKET_ERROR == retVal)
    {    
        printf("綁定套接字失敗!\n");
        closesocket(Server);    //關閉套接字
        WSACleanup();            //釋放套接字資源;
        return -1;
    }
    
    //開始監聽 
    retVal = listen(Server, 1);
    if(SOCKET_ERROR == retVal)
    {
        printf("監聽失敗!\n");        
        closesocket(Server);    //關閉套接字
        WSACleanup();            //釋放套接字資源;
        return -1;
    }
    
    //接受客戶端請求
    sockaddr_in addrClient;
    int addrClientlen = sizeof(addrClient);
    Client = accept(Server,(sockaddr FAR*)&addrClient, &addrClientlen);
    if(INVALID_SOCKET == Client)
    {
        printf("接受客戶端請求失敗!\n");        
        closesocket(Server);    //關閉套接字
        WSACleanup();            //釋放套接字資源;
        return -1;
    }
    
    //接收客戶端數據
    ZeroMemory(buf, BUF_SZIE);
    retVal = recv(Client, buf, BUF_SZIE, 0);
    if (SOCKET_ERROR == retVal)
    {
        printf("接收客戶端請求失敗!\n");        
        closesocket(Server);    //關閉套接字
        closesocket(Client);    //關閉套接字        
        WSACleanup();            //釋放套接字資源;
        return -1;
    }

    printf("%s\n", buf);    //輸出來自Client的字符串    

    //退出
    closesocket(Server);    //關閉套接字
    closesocket(Client);    //關閉套接字
    WSACleanup();            //釋放套接字資源;
    return 0;
}
Client Code:


// Client.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#define    BUF_SZIE    64
#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")

int main(int argc, char* argv[])
{

    WSADATA            wsad;            //WSADATA變量
    SOCKET            sHost;            //服務器套接字
    SOCKADDR_IN        servAddr;        //服務器地址
    char            buf[BUF_SZIE];    //接收數據緩衝區
    int                retVal;            //返回值
    
    //初始化套接字動態庫
    if (WSAStartup(MAKEWORD(2,2), &wsad) != 0)
    {
        printf("初始化套接字失敗!\n");
        return -1;
    }
    
    //建立套接字
    sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    
    if(INVALID_SOCKET == sHost)
    {
        printf("建立套接字失敗!\n");
        WSACleanup();//釋放套接字資源
        return  -1;
    }

    //設置服務器地址
    servAddr.sin_family =AF_INET;
    servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servAddr.sin_port = htons((short)2012);
    int    nServAddlen  = sizeof(servAddr);

    //鏈接服務器
    retVal=connect(sHost,(LPSOCKADDR)&servAddr, sizeof(servAddr));    
    if(SOCKET_ERROR == retVal)
    {
        printf("鏈接服務器失敗!\n");    
        closesocket(sHost);    //關閉套接字
        WSACleanup();        //釋放套接字資源
        return -1;
    }
    
    //向服務器發送數據
    ZeroMemory(buf, BUF_SZIE);
    strcpy(buf, "2012年12月13日");
    retVal = send(sHost, buf, strlen(buf), 0);
    if (SOCKET_ERROR == retVal)
    {
        printf("發送數據失敗!\n");
        closesocket(sHost);    //關閉套接字
        WSACleanup();        //釋放套接字資源
        return -1;
    }
    
    //退出
    closesocket(sHost);    //關閉套接字
    WSACleanup();        //釋放套接字資源
    return 0;
}
雖然說該程序比較簡單,可是麻雀雖小五臟俱全,程序代碼旨在突出開發TCP應用程序的框架,其中Server 、Client調用Windows Sockets API的過程以下所示:



程序運行結果: 框架



轉載請註明出處,謝謝!
socket

相關文章
相關標籤/搜索