初识Socket编程——基于流式套接字的时间同步服务器设计

实验一、基于流式套接字的时间同步服务器设计

0x00 实验内容

要求使用流式套接字编程,实现时间同步服务器和客户端,该服务器能够接收客户端的查询请求,获取本地时间,并将结果发送回客户端,客户端将该时间显示出来。过程描述如下图所示:

ClientServer请求建立连接发送系统时间ClientServer

0x01 实现过程

Server 端

// server.cpp
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <time.h>
#include <string.h>
#include <iostream>

using namespace std;

#pragma comment(lib, "ws2_32.lib") //引入动态链接库

#define MAXLINE 4096     //接收缓冲区长度
#define LISTENQ 1024     //监听队列长度
#define SEVER_PORT 13131 //时间同步服务器端口号

int main()
{
    SOCKET sock_conn;
    char buff[MAXLINE]; //缓冲区
    time_t ticks;       //时间
    int res;

    //初始化Windows Sockets DLL,协议版本号
    WORD w_version = MAKEWORD(2, 2);
    WSADATA wsa_data;

    res = WSAStartup(w_version, &wsa_data);
    if (res != 0)
    {
        cout << WSAGetLastError() << "WSAStartup Error!" << endl;
        return -1;
    }
    if (LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2)
    {
        cout << WSAGetLastError() << "Version Error!" << endl;
        WSACleanup();
        return -1;
    }

    // 设置地址
    sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;                // 设置ip协议
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // INADDR_ANY -- 0.0.0.0
    server_addr.sin_port = htons(SEVER_PORT);        //设置端口

    //创建流式套接字
    SOCKET sock_listen = socket(AF_INET, SOCK_STREAM, 0);
    if (sock_listen == INVALID_SOCKET)
    {
        cout << WSAGetLastError() << "Socket Error!" << endl;
        WSACleanup();
        return -1;
    }

    //绑定地址
    res = bind(sock_listen, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (res == SOCKET_ERROR)
    {
        cout << WSAGetLastError() << "Bind Addr Error!" << endl;
        closesocket(sock_listen);
        WSACleanup();
        return -1;
    }

    //设置监听 最长队列长度LISTENQ
    res = listen(sock_listen, LISTENQ);
    if (res == SOCKET_ERROR)
    {
        cout << WSAGetLastError() << "Listen Error!" << endl;
        closesocket(sock_listen);
        WSACleanup();
        return -1;
    }

    // 循环服务器 -- 循环处理用户的连接请求
    while (true)
    {
        //接受客户端连接请求,返回连接套接字sock_conn
        sock_conn = accept(sock_listen, nullptr, nullptr);
        if (sock_conn == INVALID_SOCKET)
        {
            cout << WSAGetLastError() << "Accept Error!" << endl;
            closesocket(sock_listen);
            WSACleanup();
            return -1;
        }

        //获取当前时间
        ticks = time(nullptr);
        time(&ticks);
        memset(buff, 0, sizeof(buff)); //清空缓冲区
        strcpy(buff, ctime(&ticks));   // 将数据转换成字符串 准备发送
        cout << "Now time is: " << buff << endl;

        //发送数据
        res = send(sock_conn, buff, (int)strlen(buff), 0);
        if (res == SOCKET_ERROR)
        {
            cout << WSAGetLastError() << "Send Error!" << endl;
            closesocket(sock_conn);
            WSACleanup();
            return -1;
        }

        cout << "Sent Time Data Successfully." << endl;

        //停止连接,不再发送数据
        res = shutdown(sock_conn, SD_SEND);
        if (res == SOCKET_ERROR)
        {
            cout << WSAGetLastError() << "Shutdown Error!" << endl;
            closesocket(sock_conn);
            WSACleanup();
            return -1;
        }

        //关闭套接字
        closesocket(sock_conn);
        cout << "Server Disconnect" << endl;
    }

    // 关闭连接
    closesocket(sock_listen);
    WSACleanup();
    return 0;
}

Client端

// client.cpp
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib") //引入动态链接库

#define MAXLINE 4096          //接收缓冲区长度
#define SEVER_PORT 13131      //时间同步服务器端口号
#define server_ip "127.0.0.1" // 服务器ip地址

int main()
{
    int res;
    char recv_data[MAXLINE + 1];

    // 初始化Windows Sockets DLL,协议版本号
    WORD w_version = MAKEWORD(2, 2);
    WSADATA wsa_data;
    res = WSAStartup(w_version, &wsa_data);
    if (res != 0)
    {
        printf("%d  WSAStartup Error!\n", WSAGetLastError());
        return -1;
    }
    if (LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2)
    {
        printf("Version Error!\n");
        WSACleanup();
        return -1;
    }

    // 设置地址
    sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;                        // 设置ip协议
    server_addr.sin_addr.S_un.S_addr = inet_addr(server_ip); //设置ip
    server_addr.sin_port = htons(SEVER_PORT);                //设置端口

    //创建流式套接字
    SOCKET sock_conn = socket(AF_INET, SOCK_STREAM, 0);
    if (sock_conn == INVALID_SOCKET)
    {
        printf("%d  Socket Error!\n", WSAGetLastError());
        WSACleanup();
        return -1;
    }

    // 请求连接服务器
    res = connect(sock_conn, (sockaddr *)&server_addr, sizeof(server_addr));
    if (res == SOCKET_ERROR)
    {
        printf("%d Connect Error!\n", WSAGetLastError());
        closesocket(sock_conn);
        WSACleanup();
        return -1;
    }

    // 清空接收缓冲区 准备接收数据
    memset(recv_data, 0, sizeof(recv_data));
    printf("Recv Data Is:");

    do
    {
        // 接收数据
        res = recv(sock_conn, recv_data, MAXLINE, 0);
        if (res > 0)
        {
            printf("%s\n", recv_data);
        }
        else
        {
            if (res == 0)
            {
                printf("Server is closed!\n");
            }
            else
            {
                printf("%d Recv Error!\n", WSAGetLastError());
            }
        }
    } while (res > 0);

    // 清理环境 断开连接 释放DLL
    closesocket(sock_conn);
    WSACleanup();
    return 0;
}
发布了46 篇原创文章 · 获赞 53 · 访问量 8万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览