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!\n");

    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!\n");

    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!\n");

            break;

        case -1:

            perror("select return failed!\n");

            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!\n");

                    goto closesocket;

                }

                time(&timet);

                //printf("Opposite: %s %s", "Server", ctime(&timet));
		printf("客户端IP:%s\n",htonl(INADDR_ANY));

		printf("服务器实现者学号:20155332\n");

		printf("%s:%s\n", "当前时间", ctime(&timet));

                strcat(buffer, "\n");

                writelen = write(0, buffer, readlen + 1);

                if(writelen < 0)

                {

                    perror("write data failed!\n");

                    goto closesocket;

                }

            }

            if(FD_ISSET(1, &readfds) > 0)

            {

                time(&timet);

                printf("Owner: %d %s\n", sockfd, ctime(&timet));
	    printf("客户端IP:%s\n",htonl(INADDR_ANY));

	    printf("服务器实现者学号:20155332\n");

            printf("%s:%s\n", "当前时间", ctime(&timet));

                memset(buffer, 0, SIZE);

                readlen = read(1, buffer, SIZE);

                if(readlen < 0)

                {

                    perror("read data failed!\n");

                    goto closesocket;

                }

                writelen = write(sockfd, buffer, readlen);

                if(writelen < 0)

                {

                    perror("write data failed!\n");

                    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!\n");

    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!\n");

    return -1;

}



if(listen(sockfd, BACKLOG) < 0)

{

    perror("listen failed!\n");

}



printf("Server is listening ......\n");



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!\n");

        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!\n");

                break;

            case -1:

                perror("select return failed!\n");

                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!\n");

                        goto closesocket;

                    }

                    time(&timet);

                    printf("Opposite: %d %s", clientfd, ctime(&timet));
		printf("客户端IP:%s\n",htonl(INADDR_ANY));

		printf("服务器实现者学号:20155332\n");

		printf("%s:%s\n", "当前时间", ctime(&timet));

                    strcat(buffer, "\n");

                    writelen = write(0, buffer, readlen+1);

                    if(writelen < 0)

                    {

                        perror("write data failed!\n");

                        goto closesocket;

                    }

                }

                if(FD_ISSET(1, &readfds) > 0)

                {

                    time(&timet);

                    /*printf("Owner: %d %s\n", sockfd, ctime(&timet));*/

		printf("客户端IP:%s\n",htonl(INADDR_ANY));

		printf("服务器实现者学号:20155332\n");

		printf("%s:%s\n", "当前时间", ctime(&timet));

                    memset(buffer, 0, SIZE);

                    readlen = read(1, buffer, SIZE);

                    if(readlen < 0)

                    {

                        perror("read data failed!\n");

                        goto closesocket;

                    }

                    writelen = write(clientfd, buffer, readlen);

                    if(writelen < 0)

                    {

                        perror("write data failed!\n");

                        goto closesocket;

                    }

                }

        }

    }

closesocket:

    close(clientfd);

}

close(sockfd);



return 0;

}
posted @ 2017-11-12 19:30  besti5332  阅读(135)  评论(0编辑  收藏  举报