zoukankan      html  css  js  c++  java
  • 大四中软实习笔记20130305

    1 Winsock网络编程

    1.1 TCP/IP网络的概念

    应用层----我们的程序、数据
    传输层----TCP/UDP  端口号      运沙子UDP   运机器TCP
    网络层----IP  计算机---计算机 可以通信了
    物理层----网卡 电压


    1.2 TCP服务器端编程步骤
    1 准备工作
    确定使用Winsock的什么版本-----1.1

    2 加载套接字
    实现使用1.1版本-----同时还会,校验本机是否支持1.1版本

    3 建立 侦听套接字(插座)-----在墙上装了1个电话插座

    4 绑定-----就是宣布自己的 IP和端口号、自己的套接字

    5 侦听----等待客户的连接请求

    6 Accept响应客户的连接请求-------通信链路 通了;而且会返回1个  连接套接字

    7 send/receive----都是通过 连接套接字


    8 关闭   连接套接字

    9 关闭 侦听套接字

    10 卸载套接字


    1.3 TCP服务器端编程步骤---翻译为C语言
    1 准备工作
    确定使用Winsock的什么版本-----1.1
    增加头文件
    #include <WINSOCK2.H>

    增加lib库
    ws2_32.lib

    2 加载套接字
    实现使用1.1版本-----同时还会,校验本机是否支持1.1版本
    int WSAStartup (
      WORD wVersionRequested,  //申请的版本号,如1.1,但要用2个字节的整型数来表示,所以填写257。            ---输入参数
      LPWSADATA lpWSAData          //这是地址类型,指向了1个结构体空间。该函数执行后,会修改该结构体数据。 ---输出参数
    );
    代码:
        WSADATA wsadata;
        LPWSADATA lpWSAData=&wsadata;
        WSAStartup(257,lpWSAData);

    3 建立 侦听套接字(插座)-----在墙上装了1个电话插座
    SOCKET socket_listen=socket(AF_INET,SOCK_STREAM,0);

    4 绑定-----就是宣布自己的 IP和端口号、自己的套接字
        struct sockaddr_in addr_b;
        addr_b.sin_addr.S_un.S_addr=inet_addr("172.18.23.200");
        addr_b.sin_port=6588;
        addr_b.sin_family=AF_INET;
        struct sockaddr * addr=(struct sockaddr *)&addr_b;
        bind(socket_listen,addr,sizeof(SOCKADDR));
       


    5 侦听----等待客户的连接请求
        listen(socket_listen,4);
    注意:4代表在线用户不能超过4个。
       

    6 Accept响应客户的连接请求-------通信链路 通了;而且会返回1个  连接套接字
        sockaddr_in addr_bb;
        sockaddr * addr_client=(sockaddr *)&addr_bb;
        int len=sizeof(sockaddr);
        SOCKET socket_connect=accept(socket_listen,addr_client,&len);
    注意:
    是阻塞函数,如果没有收到 任何客户的连接请求,程序会阻塞在这里。
    阻塞不是绝对的,有前提----该阻塞的时候就阻塞,不该阻塞就不阻塞(如套接字库加载失败了,就不阻塞了;IP地址如果设错了,也不阻塞;网线断了,也不阻塞)。
    如果,IP设置为127.0.0.1时,网线通时阻塞,不通时也阻塞。但为了使我们的服务器程序具有通用性,应该设置为127.0.0.1.

    但不能设置为127.0.0.1,因为如果这样设置,别的的PC永远也连不到服务器了。所以,它只是用来进行本机测试用的。
    所以,应该这样设置:
    addr_b.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
    但也有问题,即网线通或不通,都会阻塞。


    7 send/receive----都是通过 连接套接字
        char buf_recv[1000]={'\0'};
        recv(socket_connect,buf_recv,sizeof(buf_recv)-1,0);
        //strlen(buf_recv);
        buf_recv[999]='\0';
        printf("%s\n",buf_recv);
    注意:
    recv是阻塞函数-----网络通,而且收不大任何数据时阻塞   
    所以不阻塞时有2种情况:
    1 收到数据了,就不阻塞了,函数将运行结束,而且有返回值。
    2 如果收到数据了,返回值是数据的字节数。
    3 但此时,如果客户端的网线断了,服务器是无法知道的(因为服务器的网口是通的),一直阻塞下去
    4 如果客户端执行了关闭套接字,那么服务器端的recv会返回0(但不表示收到了0字节,而表示侦听套接字链路收到了客户端的关闭套接字请求)),此时,就又不阻塞了。
    5 如果recv返回-1,则服务器端,肯定收到了客户端的关闭套接字(请求)---通过侦听套接字的链路.
    6 如果客户端没有关闭套接字,而客户端的网线断了,则服务器是不知道的,所以recv会一直阻塞。
    7 如果客户端没有关闭套接字,但客户端程序退出了,则服务器的recv会返回-1(相当于收到了客户端的关闭套接字请求).


    解决办法:增加心跳检测代码


       
       

    8 关闭   连接套接字
        closesocket(socket_connect);

    9 关闭 侦听套接字
    closesocket(socket_listen);


    10 卸载套接字库
        WSACleanup();

    代码:

    //服务器端
    #include <stdio.h>
    #include <string.h>
    #include <WINSOCK2.H>
    
    int main()
    {
        WSADATA wsadata;
        LPWSADATA lpWSAData=&wsadata; 
        WSAStartup(257,lpWSAData);
    
        SOCKET socket_listen=socket(AF_INET,SOCK_STREAM,0);
    
        
        struct sockaddr_in addr_b;
        addr_b.sin_addr.S_un.S_addr=inet_addr("172.18.23.200"); 
        addr_b.sin_port=6588;
        addr_b.sin_family=AF_INET;
        struct sockaddr * addr=(struct sockaddr *)&addr_b;
        bind(socket_listen,addr,sizeof(SOCKADDR));
    
        listen(socket_listen,4);
    
        sockaddr_in addr_bb;
        sockaddr * addr_client=(sockaddr *)&addr_bb;
        int len=sizeof(sockaddr);
        SOCKET socket_connect=accept(socket_listen,addr_client,&len);
    
    
        char buf_recv[1000]={'\0'};
        recv(socket_connect,buf_recv,sizeof(buf_recv)-1,0);
        //strlen(buf_recv);
        buf_recv[999]='\0';
        printf("%s\n",buf_recv);
    
        closesocket(socket_connect);
    
        closesocket(socket_listen);
    
        WSACleanup();
    
    
        return 0;
    }

    1.4 TCP客户端编程步骤
    1 准备工作
    头文件、lib文件

    2 加载套接字库
    一样
        WSADATA wsadata;
        LPWSADATA lpWSAData=&wsadata;
        WSAStartup(257,lpWSAData);
       
    3 建立  客户端套接字
    一样
    SOCKET socket_client=socket(AF_INET,SOCK_STREAM,0);


    4 发生连接请求给服务器
    connect()
    不一样
    struct sockaddr_in addr_b;
        addr_b.sin_addr.S_un.S_addr=inet_addr("172.18.23.200");
        addr_b.sin_port=6588;
        addr_b.sin_family=AF_INET;
        struct sockaddr * addr=(struct sockaddr *)&addr_b;
        connect(socket_client,addr,sizeof(sockaddr));

    5 发生数据
    send()
    一样
    char buf_send[]="hello,我是客户端!";
    send(socket_client,buf_send,strlen(buf_send)+1,0);


    6 关闭套接字
    一样
    closesocket(socket_client);

    7 卸载套接字库
    一样
    WSACleanup();


    1.5 代码示例
    //客户端:

    #include <stdio.h>
    #include <string.h>
    #include <WINSOCK2.H>
    
    int main()
    {
        WSADATA wsadata;
        LPWSADATA lpWSAData=&wsadata; 
        WSAStartup(257,lpWSAData);
        
        SOCKET socket_client=socket(AF_INET,SOCK_STREAM,0);
    
        struct sockaddr_in addr_b;
        addr_b.sin_addr.S_un.S_addr=inet_addr("172.18.23.200"); 
        addr_b.sin_port=6588;
        addr_b.sin_family=AF_INET;
        struct sockaddr * addr=(struct sockaddr *)&addr_b;
        connect(socket_client,addr,sizeof(sockaddr));
    
        char buf_send[]="hello,我是客户端!";
        send(socket_client,buf_send,strlen(buf_send)+1,0);
    
        char buf_recv[1000]={'\0'};
        recv(socket_client,buf_recv,sizeof(buf_recv)-1,0);
        printf("%s\n",buf_recv);
        
    
        closesocket(socket_client);
        
        
        WSACleanup();
        
        
        return 0;
    }

    服务器端:

    #include <stdio.h>
    #include <string.h>
    #include <WINSOCK2.H>
    
    int main()
    {
        WSADATA wsadata;
        LPWSADATA lpWSAData=&wsadata; 
        WSAStartup(257,lpWSAData);
    
        SOCKET socket_listen=socket(AF_INET,SOCK_STREAM,0);
    
        
        struct sockaddr_in addr_b;
        addr_b.sin_addr.S_un.S_addr=inet_addr("172.18.23.200"); 
        addr_b.sin_port=6588;
        addr_b.sin_family=AF_INET;
        struct sockaddr * addr=(struct sockaddr *)&addr_b;
        bind(socket_listen,addr,sizeof(SOCKADDR));
    
        listen(socket_listen,4);
    
        sockaddr_in addr_bb;
        sockaddr * addr_client=(sockaddr *)&addr_bb;
        int len=sizeof(sockaddr);
        SOCKET socket_connect=accept(socket_listen,addr_client,&len);
    
    
        char buf_recv[1000]={'\0'};
        recv(socket_connect,buf_recv,sizeof(buf_recv)-1,0);
        //strlen(buf_recv);
        //buf_recv[999]='\0';
        printf("%s\n",buf_recv);
    
        char buf_send[]="我是服务器!";
        send(socket_connect,buf_send,strlen(buf_send)+1,0);
    
        closesocket(socket_connect);
    
        closesocket(socket_listen);
    
        WSACleanup();
        //system("pause");
    
    
        return 0;
    }

    1.6 改进后的代码
    服务器端:
    #include <stdio.h>
    #include <string.h>
    #include <WINSOCK2.H>
    
    int main()
    {
        WSADATA wsadata;
        LPWSADATA lpWSAData=&wsadata; 
        WSAStartup(257,lpWSAData);
    
        SOCKET socket_listen=socket(AF_INET,SOCK_STREAM,0);
    
        
        struct sockaddr_in addr_b;
        //addr_b.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); 
        addr_b.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
        addr_b.sin_port=htons(6588);
        addr_b.sin_family=AF_INET;
        struct sockaddr * addr=(struct sockaddr *)&addr_b;
        bind(socket_listen,addr,sizeof(SOCKADDR));
    
        int flag=listen(socket_listen,4);
    
        sockaddr_in addr_bb;
        sockaddr * addr_client=(sockaddr *)&addr_bb;
        int len=sizeof(sockaddr);
        SOCKET socket_connect=4576;
        socket_connect=accept(socket_listen,addr_client,&len);
    
    
        char buf_recv[1000]={'\0'};
        int count=recv(socket_connect,buf_recv,sizeof(buf_recv)-1,0);
        //strlen(buf_recv);
        //buf_recv[999]='\0';
        printf("%s\n",buf_recv);
    
        char buf_send[]="我是服务器!";
        send(socket_connect,buf_send,strlen(buf_send)+1,0);
    
        closesocket(socket_connect);
    
        closesocket(socket_listen);
    
        WSACleanup();
        //system("pause");
    
    
        return 0;
    }

    客户端:
    #include <stdio.h>
    #include <string.h>
    #include <WINSOCK2.H>
    
    int main()
    {
        WSADATA wsadata;
        LPWSADATA lpWSAData=&wsadata; 
        WSAStartup(257,lpWSAData);
        
        SOCKET socket_client=socket(AF_INET,SOCK_STREAM,0);
    
        struct sockaddr_in addr_b;
        addr_b.sin_addr.S_un.S_addr=inet_addr("172.18.23.200"); 
        addr_b.sin_port=htons(6588);
        addr_b.sin_family=AF_INET;
        struct sockaddr * addr=(struct sockaddr *)&addr_b;
        connect(socket_client,addr,sizeof(sockaddr));
    
        char buf_send[]="hello,我是客户端!";
        send(socket_client,buf_send,strlen(buf_send)+1,0);
    
        char buf_recv[1000]={'\0'};
        recv(socket_client,buf_recv,sizeof(buf_recv)-1,0);
        printf("%s\n",buf_recv);    
        
        closesocket(socket_client);    
        
        WSACleanup();
        //system("pause");
        
        return 0;
    }

  • 相关阅读:
    基于vue-cli配置移动端自适应项目
    webpack 之 resolve.alias(别名)
    vue 之引用全局样式
    webpack 3.0
    vue 之 data为什么必须声明为返回一个初始数据对象的函数?
    JS柯里化
    《css设计指南》 读书笔记 二
    《css设计指南》 读书笔记 一
    简单的移动端图片预览 包含放大缩小以及对各种手势的判定
    图片拍照上传 使用fileReader 无需跨域
  • 原文地址:https://www.cnblogs.com/blueswitkey/p/2947427.html
Copyright © 2011-2022 走看看