《網絡安全編程基礎》之Socket編程

《網絡安全編程基礎》之Socket編程

個人代碼

server.c

// server.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Winsock2.h>
#pragma comment(lib,"ws2_32.lib") //添加靜態連接庫文件
void main(int argc,char* argv[])
{
    WSADATA wsadata;
    WSAStartup(MAKEWORD(1,1),&wsadata);

    SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0); //socket()
    /***地址結構體***/
    SOCKADDR_IN addrSvr;
    addrSvr.sin_family=AF_INET;
    addrSvr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
    addrSvr.sin_port=htons(6000);
    /**************/
    bind(sockSrv,(SOCKADDR*)&addrSvr, sizeof(SOCKADDR)); //bind()
    listen(sockSrv,5); //listen()
    SOCKADDR_IN addrClient;
    int len= sizeof(SOCKADDR);
    while(1) //加循環是爲了應對多個客戶端鏈接此服務器的狀況
    {
        SOCKET socksend=accept(sockSrv,(SOCKADDR*)&addrClient,&len); //accept()
        char sendBuf[50]; //
        sprintf(sendBuf,"你好,我是服務器"); //使用sprintf給字符串賦值、鏈接字符串比較方便
        send(socksend,sendBuf,strlen(sendBuf)+1,0); //send(),+1是由於字符串以'\0'結尾
        char recvBuf[50];
        recv(socksend,recvBuf,50,0); //recv()
        printf("%s\n",recvBuf);
        closesocket(socksend);
    }
    /*closesocket(sockSrv);
    WSACleanup();*/ //while(1)後的死代碼
}

client.c

// Client.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Winsock2.h>
#pragma comment(lib,"ws2_32.lib") //添加靜態連接庫文件
void main(int argc,char* argv[])
{
    WSADATA wsadata;
    WSAStartup(MAKEWORD(1,1),&wsadata);

    SOCKET socketClient=socket(AF_INET,SOCK_STREAM,0); //socket()
    /***地址結構體***/
    SOCKADDR_IN addrSvr;
    addrSvr.sin_family=AF_INET;
    addrSvr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
    addrSvr.sin_port=htons(6000);
    /**************/
    connect(socketClient,(SOCKADDR*)&addrSvr,sizeof(SOCKADDR)); //connect()
    char recvBuf[50];
    recv(socketClient,recvBuf,50,0); //recv()
    printf("%s\n",recvBuf);
    send(socketClient,"你好,我是客戶端",strlen("你好,我是客戶端")+1,0);  //send()
    closesocket(socketClient);

    WSACleanup();
}

代碼調試過程當中出現的問題

問題一:macOS High Sierra下Clion出現CMake Error

toDJA.jpg

解決辦法:百度無果,從新打開Clion發現連license都過時了,多半是沒救了,只能老老實實用命令行試試了>_<
toBid.png

問題二:終端下編譯server.c提示找不到"winsock2.h"頭文件

torRI.png

解決辦法:

Mac下編程用什麼替換windows.h頭文件?html

  • 我在mac下編程,想使用清屏指令cls很差使,也不能用windows.h頭文件。請你們幫我想一想怎麼辦。還有在mac下能用system" "麼?macos

  • 不行,你不能在除了 Windows 的任何系統上使用 Windows.h。你要理解 API 的概念,windows.h 這個頭文件是 Windows 帶的,而不是 C 語言自身有的。事實上,出了 Windows,沒有任何系統——實際上也是在真真切切用 C 的系統——例如全部在跑類 Unix,好比 OS X、Linux 甚至 FreeBSD 上的,都不能用 Windows 這套 API。這也是爲何坊間都說 OS X 是適合作編程,特別是適合學編程的,由於 OS X 是「體制內」,也就使用和全世界除了 Windows 以外全部的東西都互通的底層架構的,並且它在過去的大部分時候都要比各種 Linux 要容易上手,所謂的「更優雅」。
  • ……編程

在百度知道上看到了這段對話後感受已經涼了,還好我有windows8.1虛擬機,這回不再怕找不到windows頭文件了吧!windows

問題三:windows8.1虛擬機不兼容VC6.0

towIH.png
toszt.png

解決辦法:

  1. 右擊Visual C++ 6.0快捷方式,選擇"屬性",在"目標(T):"中查看其可執行文件的地址爲:"C:\Program Files (x86)\Microsoft Visual Studio\Common\MSDev98\Bin\MSDEV.EXE",找到MSDEV.EXE;
  2. 右鍵選擇"屬性",在"常規"選項卡下將MSDEV.EXE改名爲MSDEV1.EXE:
    to6QP.png
  3. 在"兼容性"選項卡下勾選"以兼容模式運行這個程序",將兼容模式選擇Windows XP(Service Pack2)",並將權限等級勾選爲「以管理員身份運行此程序」,點擊肯定
    tocsf.png
  4. 從新運行Visual C++ 6.0,奈斯,已經成功了!
    togL8.png
  5. 老規矩,新建一個Win32控制檯工程,並以Hello World方式打開:
    toReS.png
    toWdg.png
  6. 盡情開始你的表演吧~

問題四:編譯error1——在編譯VC時候,出現fatal error C1010: unexpected end of file while looking for precompiled head

tofoQ.png

問題詳細解釋:

致命錯誤C1010,在尋找預編譯指示頭文件時,文件未預期結束。就是沒有找到預編譯指示信息的問文件。顧名思義就是預編譯由於缺乏了預編譯文件而失敗。解決方法顯然能夠取消預編譯,或者幫助編譯器找到預編譯文件。數組

解決辦法:

  1. 右鍵單擊項目工程中的cpp文件,在菜單Project-->Settings-->C/C++-->Precompile Header,設置爲第一項:Not using precompile headers。
    to4ij.png
  2. 在.cpp文件開頭添加包含文件stdafx.h:#include "stdafx.h"
  3. 從新編譯便可~

問題五:編譯error2——地址結構體大小寫表示問題

to5Js.png

解決辦法:

不知道是否是編譯環境不一樣的緣由,學校電腦上的地址結構體成員addrSvr.sin_Family到我win8.1虛擬機上就必須改爲addrSvr.sin_family了,滿臉黑線= =
toIWn.png安全

問題六:編譯error3——sendBuf未定義

toozq.png

解決辦法:

本身疏忽緣由,在前面加上char sendBuf[50]便可~
至此,編譯終於成功經過orz...
to7Q0.png
tTZYd.png服務器

問題七:燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙燙

點擊運行,彈出Windows防火牆……
toHyV.png
點擊"容許訪問"後,額……
toLeU.png
tTa60.png
tTb9A.png
??☺???網絡

解決辦法:

百度一下,發現又打開了一個新世界的大門:架構

問題根源:app

在windows平臺下,ms的編譯器(也就是vc帶的那個)在 Debug 模式下,會把未初始化的棧內存所有填成 0xcc,用字符串來看就是」燙燙燙燙燙燙燙」,未初始化的堆內存所有填成0xcd,字符串看就是「屯屯屯屯屯屯屯屯」。

說人話:定義的字符串沒有初始化就會出現這樣的狀況

解決辦法:初始化一下

  1. char p[] = 「0」;
  2. ZeroMemory
  3. memset

那麼這裏是因爲先運行client.c再運行server.c致使
char recvBuf[50]; recv(socksend,recvBuf,50,0); //recv()中數組recvBuf未被初始化的緣由,解決方法固然是先運行server.c再運行client.c咯,這樣客戶端就能receive到服務器發來的recvBuf啦~

運行結果

  • 一個客戶端鏈接一個服務器:
    tobLT.png
  • 多個客戶端同時鏈接一個服務器:
    toOwF.png

高級版mySocket——實現服務器客戶端互發消息尬聊>_<

核心僞代碼

  • server.c:

    do{
        gets(sendBuf);
        send();
        recv();
        puts(recvBuf);
    }while(返回值不爲-1);
  • client.c:

    do{
        recv();
        puts(recvBuf);
        gets(sendBuf);
        send();
    }while(返回值不爲-1);

完整代碼

  • server.c:

    // server.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <Winsock2.h>
    #include <string.h>
    #pragma comment(lib,"ws2_32.lib") //添加靜態連接庫文件
    void main(int argc,char* argv[])
    {
        WSADATA wsadata;
        WSAStartup(MAKEWORD(1,1),&wsadata);
    
        SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0); //socket()
        /***地址結構體***/
        SOCKADDR_IN addrSvr;
        addrSvr.sin_family=AF_INET;
        addrSvr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
        addrSvr.sin_port=htons(6000);
        /**************/
        bind(sockSrv,(SOCKADDR*)&addrSvr, sizeof(SOCKADDR)); //bind()
        listen(sockSrv,5); //listen()
        SOCKADDR_IN addrClient;
        int len= sizeof(SOCKADDR);
        while(1)
        {
            SOCKET socksend=accept(sockSrv,(SOCKADDR*)&addrClient,&len); //accept()
            char sendBuf[50]; 
            char recvBuf[50];
            int a;
            do{
                printf("Me:");
                gets(sendBuf);
                fflush(stdin);
                send(socksend,sendBuf,strlen(sendBuf)+1,0); //send(),+1是由於字符串以'\0'結尾
                a=recv(socksend,recvBuf,50,0); //recv()
                printf("  Client:%s\n",recvBuf);
            }while(a!=-1);
    
            closesocket(socksend);
        }
            closesocket(sockSrv);
            WSACleanup();
    }
  • client.c:

    // Client.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <Winsock2.h>
    #pragma comment(lib,"ws2_32.lib") //添加靜態連接庫文件
    void main(int argc,char* argv[])
    {
        WSADATA wsadata;
        WSAStartup(MAKEWORD(1,1),&wsadata);
    
        SOCKET socketClient=socket(AF_INET,SOCK_STREAM,0); //   socket()
        /***地址結構體***/
        SOCKADDR_IN addrSvr;
        addrSvr.sin_family=AF_INET;
        addrSvr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
        addrSvr.sin_port=htons(6000);
        /**************/
        connect(socketClient,(SOCKADDR*)&addrSvr,sizeof(SOCKADDR));
        char recvBuf[50];
        char sendBuf[50];
        int a;
        do{
            a=recv(socketClient,recvBuf,50,0);
            printf("        Server:%s\n",recvBuf);
            printf("Me:");
            gets(sendBuf);
            fflush(stdin);
            send(socketClient,sendBuf,strlen(sendBuf)+1,0);
        }while(a!=1);
    
        closesocket(socketClient);
    
        WSACleanup();
    }

運行結果(這不是尬聊是什麼hhh)

UKuNV.png

參考資料

相關文章
相關標籤/搜索