• 2016-2017第一学期 20155332 第八周课堂实践


    2016-2017第一学期 20155332 第八周课堂实践

    1. socket套接字介绍

    • socket机制其实就是包括socket, bind, listen, connect, accept等函数的方法,其通过指定的函数实现不同的协议(IP4,IP6等)的数据在不同层之间的传输和获取等处理。其实个人理解socket就是处于应用层和TCP/IP协议之间的一个中间层,具体的数据分析,重组,拆分等操作对于应用层的网络编程者来说都是不可见的,这些都有协议栈内核实现,应用层的网络编程会通过设置socket机制中创建socket时参数不同,而接收或者发送不同类型的数据。

    • 对于TCP/IP在这里就不过多的讲,但是需要提及的是经典的TCP/IP参考模型是分为4个层次:应用层,传输层,网络互联层,主机到网络层。标准的套接字编程主要是指TCP和UDP的网络编程,socket网络编程的模式就是分server和client,通过server端首先建立,client端联接进行通信。网络协议栈内核实现的功能主要就是在数据到达每一层时,给数据加上或者去掉协议包头,或者进行校验,数据重组,拆分等操作,最后得到我们想要的数据格式。

    • 下面简单列一下TCP/IP参考模型中主要的协议类型

    • 标准套接字分为TCP和UDP协议两种不同type的工作流程,TCP网络编程相对于UDP来说相对复杂,因为TCP是面向连接的服务,其中包括三次握手建立连接的过程,而UDP则是无连接的服务,下图介绍了TCP服务使用socket套接字建立连接的过程,以及进行数据交互的过程。

    • TCP和UDP的网络编程模式有两种,一种是服务器模式,另一种是客户端模式,因为TCP是面向连接的服务,所以在socket机制当中,TCP的服务器模式比UDP的服务器模式多了listen,accept函数,TCP客户端比UDP客户端多了connect函数。下面是TCP和UDP网络编程的两种模式流程图。下面将结合图2,3,4介绍一下TCP socket的机制是如何实现的。


    • TCP 服务器端与客户端通信流程


    • UDP服务器端和客户端通信流程

    客户端代码

    #include <stdio.h>
    
    #include <string.h>
    
    #include <sys/select.h>
    
    #include <sys/socket.h>
    
    #include <netinet/in.h>
    
    #include <time.h>
    
    
    
    #define SPORT 8888
    
    #define SIZE 100
    
    
    
    int main(void)
    
    {
    
    int sockfd, clientfd; 
    
    struct sockaddr_in sockServer;
    
    struct timeval tv;
    
    fd_set readfds;
    
    int readlen, writelen;
    
    char buffer[SIZE];
    
    time_t timet;
    
    
    
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
    if(sockfd < 0)
    
    {
    
        perror("create socket failed!
    ");
    
        return -1;
    
    }
    
    
    
    bzero(&sockServer, 0);
    
    sockServer.sin_family = AF_INET;
    
    sockServer.sin_port = htons(SPORT);
    
    sockServer.sin_addr.s_addr = htonl(INADDR_ANY);
    
    
    
    if(connect(sockfd, (struct sockaddr *)&sockServer, sizeof(struct sockaddr_in)) < 0)
    
    {
    
        perror("connect failed!
    ");
    
        close(sockfd);
    
    }    
    
    
    
    while(1)
    
    {
    
        int ret;
    
        
    
        FD_ZERO(&readfds);
    
        FD_SET(1, &readfds);
    
        FD_SET(sockfd, &readfds);
    
        tv.tv_usec = 0;
    
        tv.tv_sec = 60;
    
        
    
        ret = select(sockfd+1, &readfds, NULL, NULL, &tv);
    
        switch(ret)
    
        {
    
            case 0:
    
                printf("select timeout!
    ");
    
                break;
    
            case -1:
    
                perror("select return failed!
    ");
    
                goto closesocket;
    
            default:
    
                if(FD_ISSET(sockfd, &readfds) > 0)
    
                {
    
                    memset(buffer, 0, SIZE);
    
                    readlen = read(sockfd, buffer, SIZE);
    
                    if(readlen < 0)
    
                    {
    
                        perror("read data failed!
    ");
    
                        goto closesocket;
    
                    }
    
                    time(&timet);
    
                    //printf("Opposite: %s %s", "Server", ctime(&timet));
    		printf("客户端IP:%s
    ",htonl(INADDR_ANY));
    
    		printf("服务器实现者学号:20155332
    ");
    
    		printf("%s:%s
    ", "当前时间", ctime(&timet));
    
                    strcat(buffer, "
    ");
    
                    writelen = write(0, buffer, readlen + 1);
    
                    if(writelen < 0)
    
                    {
    
                        perror("write data failed!
    ");
    
                        goto closesocket;
    
                    }
    
                }
    
                if(FD_ISSET(1, &readfds) > 0)
    
                {
    
                    time(&timet);
    
                    printf("Owner: %d %s
    ", sockfd, ctime(&timet));
    	    printf("客户端IP:%s
    ",htonl(INADDR_ANY));
    
    	    printf("服务器实现者学号:20155332
    ");
    
                printf("%s:%s
    ", "当前时间", ctime(&timet));
    
                    memset(buffer, 0, SIZE);
    
                    readlen = read(1, buffer, SIZE);
    
                    if(readlen < 0)
    
                    {
    
                        perror("read data failed!
    ");
    
                        goto closesocket;
    
                    }
    
                    writelen = write(sockfd, buffer, readlen);
    
                    if(writelen < 0)
    
                    {
    
                        perror("write data failed!
    ");
    
                        goto closesocket;
    
                    }
    
                }
    
        }
    
    
    
    closesocket:
    
        close(clientfd);
    
    }
    
    close(sockfd);
    
    
    
    return 0;
    
    }
    

    服务器代码

    #include <stdio.h>
    
    #include <string.h>
    
    #include <sys/select.h>
    
    #include <sys/socket.h>
    
    #include <netinet/in.h>
    
    #include <time.h>
    
    #define SPORT 8888
    
    #define BACKLOG 5
    
    #define SIZE 100
    
    int main(void)
    
    {
    
    int sockfd, clientfd; 
    
    struct sockaddr_in sockServer, sockClient;
    
    struct timeval tv;
    
    fd_set readfds, writefds;
    
    int readlen, writelen;
    
    char buffer[SIZE];
    
    
    
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
    if(sockfd < 0)
    
    {
    
        perror("create socket failed!
    ");
    
        return -1;
    
    }
    
    
    
    bzero(&sockServer, 0);
    
    sockServer.sin_family = AF_INET;
    
    sockServer.sin_port = htons(SPORT);
    
    sockServer.sin_addr.s_addr = htonl(INADDR_ANY);
    
    
    
    if(bind(sockfd, (struct sockaddr *)&sockServer, sizeof(struct sockaddr_in)) < 0)
    
    {
    
        perror("bind socket failed!
    ");
    
        return -1;
    
    }
    
    
    
    if(listen(sockfd, BACKLOG) < 0)
    
    {
    
        perror("listen failed!
    ");
    
    }
    
    
    
    printf("Server is listening ......
    ");
    
    
    
    while(1)
    
    {
    
        int len = sizeof(struct sockaddr_in);
    
        int ret;
    
        time_t timet;
    
        
    
        clientfd = accept(sockfd, (struct sockaddr *)&sockClient, &len);
    
        if(clientfd < 0)
    
        {
    
            perror("accept failed!
    ");
    
            return -1;
    
        }
    
        
    
        for(;;)
    
        {
    
            FD_ZERO(&readfds);
    
            FD_SET(1, &readfds);
    
            FD_SET(clientfd, &readfds);
    
            tv.tv_usec = 0;
    
            tv.tv_sec = 60;
    
            
    
            ret = select(clientfd+1, &readfds, NULL, NULL, &tv);
    
            switch(ret)
    
            {
    
                case 0:
    
                    printf("select timeout!
    ");
    
                    break;
    
                case -1:
    
                    perror("select return failed!
    ");
    
                    goto closesocket;
    
                default:
    
                    if(FD_ISSET(clientfd, &readfds) > 0)
    
                    {
    
                        memset(buffer, 0, SIZE);
    
                        readlen = read(clientfd, buffer, SIZE);
    
                        if(readlen < 0)
    
                        {
    
                            perror("read data failed!
    ");
    
                            goto closesocket;
    
                        }
    
                        time(&timet);
    
                        printf("Opposite: %d %s", clientfd, ctime(&timet));
    		printf("客户端IP:%s
    ",htonl(INADDR_ANY));
    
    		printf("服务器实现者学号:20155332
    ");
    
    		printf("%s:%s
    ", "当前时间", ctime(&timet));
    
                        strcat(buffer, "
    ");
    
                        writelen = write(0, buffer, readlen+1);
    
                        if(writelen < 0)
    
                        {
    
                            perror("write data failed!
    ");
    
                            goto closesocket;
    
                        }
    
                    }
    
                    if(FD_ISSET(1, &readfds) > 0)
    
                    {
    
                        time(&timet);
    
                        /*printf("Owner: %d %s
    ", sockfd, ctime(&timet));*/
    
    		printf("客户端IP:%s
    ",htonl(INADDR_ANY));
    
    		printf("服务器实现者学号:20155332
    ");
    
    		printf("%s:%s
    ", "当前时间", ctime(&timet));
    
                        memset(buffer, 0, SIZE);
    
                        readlen = read(1, buffer, SIZE);
    
                        if(readlen < 0)
    
                        {
    
                            perror("read data failed!
    ");
    
                            goto closesocket;
    
                        }
    
                        writelen = write(clientfd, buffer, readlen);
    
                        if(writelen < 0)
    
                        {
    
                            perror("write data failed!
    ");
    
                            goto closesocket;
    
                        }
    
                    }
    
            }
    
        }
    
    closesocket:
    
        close(clientfd);
    
    }
    
    close(sockfd);
    
    
    
    return 0;
    
    }
  • 相关阅读:
    hdu 1541 Stars(经典BIT)
    CODE[VS] 1082 线段树练习3(区间修改+区间查询)
    Luogu P3368 【模板】树状数组 2(区间修改,单点查询)
    牛客小白月赛5-I-区间(差分求前缀和+一次暴力统计)
    牛客小白月赛5-J-时间(time) (简单模拟)
    牛客小白月赛5-D-阶乘(求n内每个数的阶乘相乘后尾数为0的个数)
    CF1110C Meaningless Operations(构造题)
    洛谷4859 BZOJ3622 已经没什么好害怕的了(DP,二项式反演)
    二项式反演学习笔记
    UVAlive-7040 color(组合数学,二项式反演)
  • 原文地址:https://www.cnblogs.com/besti2015/p/7822546.html
Copyright © 2020-2023  润新知