《网络安全编程基础》之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

参考资料

相关文章
相关标签/搜索