利用I/O复用模型实现一个时间同步服务器

利用I/O复用模型实现一个时间同步服务器

一、实验内容

  • 服务端采用I/O复用模型(select函数)接收客户端的时间同步请求
  • 服务端采用单线程,但要能同时接收多客户端的连接请 求,显示客户端IP和端口,并向其回送时间信息。
  • 客户端尝试同时使用 UDP 和 TCP 来实现。
  • 注:借助 I/O 复用模型,用单线程达到多线程的效果。

二、实验要求

  提交源码(源码编写要规范)、可执行程序、实验报告(要有程序运行截图)。

三、实验分析

select 介绍

  select函数的作用是监听指定的多个I/O的文件描述符,在设定的时间内阻塞,当有一个或者多个I/O端口满足某个“读”或者“写”的条件,则在fd_set类型参数中标记并返回。
  fd_set类型是一个默认大小为1024位的类型,每一位代表一个I/0文件描述符。例如每个进程默认0、1、2分别表示标准输入、标准输出和标准错误输出,所以fd_set类型1024位中0、1、2位分别代表标准输入、标准输出和标准错误输出。同理假如进程里创建了一个监听socket文件描述符为3,则fd_set的第3位代表这个监听sockfd;假如用accept了客户端连接返回一个fdSocket为n,那么fd_set的第n个位就代表这个fdSocket。(因为在一个进程里,某个I/O口的文件描述符是唯一的。)

fd_set fdRead,fdSocket;
FD_ZERO (&fdSocket);//将fdset所有“位”置0
FD_SET(TcpServerSocket,&fdSocket);
FD_SET(UdpServerSocket,&fdSocket);

server

#include <iostream>
#include <WinSock2.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

using namespace std;

#pragma comment (lib,"ws2_32.lib")

#define BUFFER_LEN 1024
#define IP_ADDRESS "127.0.0.1"
#define PORT 8888

int main()
{
    WSADATA Ws;
    WORD sockVersion = MAKEWORD(2,2);

    SOCKET TcpServerSocket = INVALID_SOCKET;
    SOCKET UdpServerSocket = INVALID_SOCKET;
    SOCKET ConnectSocket = INVALID_SOCKET;

    if ( WSAStartup(sockVersion, &Ws) != 0 )
    {
        cout<<"Init Windows Socket Failed:"<<GetLastError()<<endl;
        closesocket(ConnectSocket);
        return -1;
    }

    sockaddr_in ClientAddr;

    char recvbuf[BUFFER_LEN];
    char sendbuf[BUFFER_LEN];
    int iResult;
    // 创建用于监听的套接字
    TcpServerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if ( TcpServerSocket == INVALID_SOCKET )
    {
        cout<<"Create Socket Failed:"<<GetLastError()<<endl;
        closesocket(TcpServerSocket);
        WSACleanup();
        return -1;
    }

    // 为套接字绑定地址和端口号
    // 监听端口为DEFAULT_PORT
    struct sockaddr_in serAddr;
    serAddr.sin_family = AF_INET;
    serAddr.sin_port = htons(PORT);
    serAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
    memset(serAddr.sin_zero,0x00,8);

    int Addrlen = sizeof(serAddr);

    SYSTEMTIME time;
    GetLocalTime(&time);

    iResult = bind(TcpServerSocket, (struct sockaddr*)&serAddr, sizeof(serAddr));
    if(iResult == SOCKET_ERROR)
    {
        cout<<"Bind Error !"<<endl;
        return -1;
    }

    sockaddr_in remoteAddr;
    int nAddrLen = sizeof(remoteAddr);
    UdpServerSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    iResult = bind(UdpServerSocket,(struct sockaddr *)&serAddr,sizeof(serAddr));
    if(iResult == SOCKET_ERROR)
    {
        cout<<"Bind Error !"<<endl;
        return -1;
    }

    // 监听套接字
    iResult = listen(TcpServerSocket,SOMAXCONN);
    if(iResult == SOCKET_ERROR)
    {
        cout<<"---Listen Failed ---!"<<endl;
        closesocket(TcpServerSocket);
        WSACleanup();
        return -1;
    }

    cout<<"---Server
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值