1. 程式人生 > >獲取時間程式(客戶端和伺服器)

獲取時間程式(客戶端和伺服器)

一個獲取時間的程式

vs2013 windows8.1

********************************客戶端**********************************

// 獲取時間客戶程式.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include "pack.h"
#include <WinSock2.h>   //因為是在windows上程式設計,所以用這個標頭檔案
#include "unp.h"
#pragma comment(lib,"ws2_32")  //windows上要用到的

#define MAXLINE 4096
#define SA struct sockaddr *

int _tmain(int argc, _TCHAR* argv[])
{
    std::cout << "獲取時間客戶端程式" << std::endl;

    //這兩句在windows程式設計要用到
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    int sockfd, n;  
    char recvline[MAXLINE + 1];
    struct sockaddr_in servaddr;   //ip的sockaddr結構
    int iCount = 0;

    //用socket套接字建立一個插口描述符,並在其中指定所用的協議 AF_INET指Internet協議,SOCK_STREAM指TCP

    //這裡的socket用了書上介紹的包裹函式,在這裡面我只包裹了這一個。。。,他這裡的包裹叫法應該就是所謂的封裝吧  

   sockfd = Socket(AF_INET, SOCK_STREAM, 0); 

    bzero(&servaddr, sizeof(servaddr));  //windows版本好像沒bzero,用的是memset,書上介紹了可以用巨集寫過一遍,避免參數使用錯誤
    servaddr.sin_family = AF_INET;  
    servaddr.sin_port = htons(9999);  //試了13(知名埠),好像都可以,只要不是正在使用的埠就可以了
    servaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); 

    //connect用來連線伺服器,第二個引數指向ip的地址結構,SA巨集只是單純的縮小程式碼

    //connect如果連線伺服器成功,會返回一個大於0的值,如果在沒用啟動伺服器的時候,開啟客戶端的時候就會出現這個輸出   

    //connect 相當於執行主動開啟

   if (connect(sockfd, (SA)&servaddr, sizeof(servaddr)) < 0)
        std::cout << "connect 錯誤" << '\n';

    //迴圈輸出,其實在這裡就輸出一遍,

    //recv用來接收從伺服器獲取的資料,第二個引數是接收緩衝區的大小,第三個引數是大小(感覺不太對)

    //recv返回值是接收資料的最後一個+1

    while ((n = recv(sockfd, recvline, MAXLINE, 0)) > 0)
    {
        recvline[n] = 0;   //結束字元,(為啥不是‘\0')
        std::cout << asTime(recvline) << '\n';    //傳過來的是C字串,把他轉換一個日曆時間值(國外的格式)
        //std::cout << recvline << '\n';  //時間戳值
    }

    closesocket(sockfd);
    WSACleanup();

    std::cin.get();
    std::cin.get();
    return 0;
}

//*****************************unp.h***********************************
#ifndef __UNP_H__
#define __UNP_H__

#include <ctime>
#include <string>
#include <iostream>

#ifndef HAVA_BZEOR
#define bzero(ptr,n) memset(ptr,0,n)
#endif

/*
將一個時間戳字元指標傳進來,轉換為一個字串
引數1:一個字元指標
返回值:一個日曆時間字串的指標
*/
std::string asTime(char *t)
{
    const int LENGTH = 26;
    std::time_t ti= atol(t);  //將C字串轉換為一個長整型(時間戳型)
    char tmp[LENGTH];
    ctime_s(tmp, LENGTH, &ti); //將一個時間戳值轉化為C字串
    return tmp;
}

#endif

********************************pack.h           pack.cpp*********************

#ifndef __PACK_H__
#define __PACK_H__

int Socket(int family, int type, int protocol);

#endif

#include "stdafx.h"
#include <WinSock2.h>
#include <iostream>

int Socket(int family, int type, int protocol)
{
    int n;
    if ((n = socket(family, type, protocol)) < 0)
    {
        std::cout << "socket 錯誤" << std::endl;
    }
    return n;
}

************************************伺服器程式***********************

// 獲取時間客戶程式伺服器.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <time.h>
#include <string>
#include <WinSock2.h>
#include "unp.h"
#pragma comment(lib,"ws2_32")

#define MAXLINE 4096
#define SA sockaddr *
#define LISTENQ 2


int _tmain(int argc, _TCHAR* argv[])
{
    std::cout << "獲取時間伺服器" << std::endl;

    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    int listenfd, connfd;
    struct sockaddr_in servaddr;
    char buff[MAXLINE];
    time_t ticks;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);  //伺服器IP地址一般設為萬用字元
    servaddr.sin_port = htons(9999);

    bind(listenfd, (SA)&servaddr, sizeof(servaddr));

    listen(listenfd, LISTENQ);

    //socket bind listen 相當於TCP的3次握手
    for (;;)
    {

        connfd = accept(listenfd, (SA)NULL, NULL);

        ticks = time(NULL);
        std::string tim = std::to_string(ticks);    
            
        ctime_s(buff, 30, &ticks);

        std::cout << ticks << " " << buff <<'\n';
        send(connfd, tim.c_str(), strlen(tim.c_str()),NULL);

        closesocket(connfd);
    }

    closesocket(listenfd);          //關閉監聽socket

    WSACleanup();              //解除安裝

    std::cin.get();
    std::cin.get();
    return 0;
}

*****************************************************************************************************

先啟動伺服器的程式

然後啟動客戶端程式



感覺理解的還不夠透徹,還有點問題