天天看點

網絡程式設計練習這些就ok

1,什麼是C/S架構?

C指的是client(用戶端軟體),S指的是Server(服務端軟體)
    一個C/S架構就是,實作服務端軟體與用戶端軟體基于網絡通信。

網際網路中處處是C/S架構
      如12306網站是服務端,你的浏覽器是用戶端(B/S架構也是C/S架構的一種)
      騰訊作為服務端為你提供視訊,你得下個騰訊視訊用戶端才能看它的視訊)

C/S架構與socket的關系:
        我們學習socket就是為了完成C/S架構的開發
      

  

2,網際網路協定是什麼?分别介紹五層協定中每一層的功能?

英語成為世界上所有人通信的統一标準,計算機之間的通信也應該有一個像英語一樣的通信标準,
這個标準稱之為網際網路協定, 可以很明确地說:網際網路協定就是計算機界的英語,網絡就是實體連結
媒體+網際網路協定。 我們需要做的是,讓全世界的計算機都學會網際網路協定,這樣任意一台計算機在
發消息時都嚴格按照協定規定的格式去組織資料,接收方就可以按照相同的協定解析出結果了,這就
實作了全世界的計算機都能無障礙通信。 按照功能不同,人們将網際網路協定分為osi七層或tcp/ip五
層或tcp/ip四層(我們隻需要掌握tcp/ip五層協定即可),這種分層就好比是學習英語的幾個階段,
每個階段應該掌握專門的技能或者說完成特定的任務,比如:1、學音标 2、學單詞 3、學文法 4、寫作文
      
簡單說,計算機之間的通信标準,就稱為網際網路協定

    按照功能不同,人們将網際網路協定分為osi七層或tcp/ip五層或tcp/ip四層

    tcp/ip四層:應用層,傳輸層,網絡層,網絡接口層

    tcp/ip五層:應用層,傳輸層,網絡層,資料鍊路層,實體層

    osi七層:應用層,表示層,會話層,傳輸層,網絡層,資料鍊路層,實體層
      

3,基于tcp協定通信,為何建立連結需要三次握手,而斷開連結卻需要四次揮手

為什麼要三次揮手?

  在隻有兩次“握手”的情形下,假設Client想跟Server建立連接配接,但是卻因為中途連接配接請求的
資料報丢失了,故Client端不得不重新發送一遍;這個時候Server端僅收到一個連接配接請求,是以
可以正常的建立連接配接。但是,有時候Client端重新發送請求不是因為資料報丢失了,而是有可能
資料傳輸過程因為網絡并發量很大在某結點被阻塞了,這種情形下Server端将先後收到2次請求,
并持續等待兩個Client請求向他發送資料...問題就在這裡,Cient端實際上隻有一次請求,而
Server端卻有2個響應,極端的情況可能由于Client端多次重新發送請求資料而導緻Server端
最後建立了N多個響應在等待,因而造成極大的資源浪費!是以,“三次握手”很有必要!

  為什麼要四次揮手?

  試想一下,假如現在你是用戶端你想斷開跟Server的所有連接配接該怎麼做?
第一步,你自己先停止向Server端發送資料,并等待Server的回複。但事情還沒有完,
雖然你自身不往Server發送資料了,但是因為你們之前已經建立好平等的連接配接了,
是以此時他也有主動權向你發送資料;故Server端還得終止主動向你發送資料,
并等待你的确認。其實,說白了就是保證雙方的一個合約的完整執行!
      

  三次握手:client發送請求建立通道;server收到請求并同意,同時也發送請求建通道;client收到請求并同意,建立完成

  四次揮手:client發送請求斷開通道;server收到請求并同意,同時還回複client上一條消息;server也發送請求斷開通道;client受到消息結束

為什麼TCP協定終止連結要四次?

1、當主機A确認發送完資料且知道B已經接受完了,想要關閉發送資料口(當然确認信号還是可以發),
就會發FIN給主機B。

2、主機B收到A發送的FIN,表示收到了,就會發送ACK回複。

3、但這是B可能還在發送資料,沒有想要關閉資料口的意思,是以FIN與ACK不是同時發送的,
而是等到B資料發送完了,才會發送FIN給主機A。

4、A收到B發來的FIN,知道B的資料也發送完了,回複ACK, A等待2MSL以後,沒有收到B傳來的
任何消息,知道B已經收到自己的ACK了,A就關閉連結,B也關閉連結了。
      

4,為何基于tcp協定的通信比基于udp協定的通信更可靠?

tcp:可靠 對方給了确認收到資訊,才發下一個,如果沒收到确認資訊就重發

udp:不可靠 一直發資料,不需要對方回應

(1)UDP:user datagram protocol(使用者資料報協定)
特點:
——1:面向無連接配接:傳輸資料之前源端和目的端不需要建立連接配接
——2:每個資料報的大小都限制在64k(8個位元組)以内
——3:面向封包的不可靠協定(即發出去的資料不一定會接收到)
——4:傳輸速率快,效率高
——5:現實生活執行個體:郵局寄件,實時線上聊天,視訊協定等等
(2)TCP:transmission control protocol(傳輸控制協定)
 特點:
——1:面向連接配接:傳輸資料之前需要建立連接配接
——2:在連接配接過程中進行大量的資料傳輸
——3:通過“三次握手”的方式完成連接配接,是安全可靠的協定
——4:傳輸效率低,速度慢
 
      

‍5,流式協定指的是什麼協定,資料報協定指的是什麼協定?

TCP協定,可靠傳輸
資料報協定: UDP協定,不可傳輸
也就是TCP和UDP的差別:
    TCP是面向連接配接的,可靠的位元組流服務
    UDP是面向無連接配接的資料報服務
      

6,什麼是socket?簡述基于tcp協定的套接字通信流程流式協定:

Socket是應用層與TCP/IP協定族通信的中間軟體抽象層,它是一組接口。在設計模式中,
Socket其實就是一個門面模式,它把複雜的TCP/IP協定族隐藏在Socket接口後面,
對使用者來說,一組簡單的接口就是全部。

服務端:建立socket對象,綁定ip端口bind(),  設定最大連結數listen(),  accept()與用戶端
的connect()建立雙向管道, send(), recv(),close()

用戶端:建立socket對象,connect()與服務端accept()建立雙向管道 ,  send(), recv(),close()
      

7,什麼是粘包? socket 中造成粘包的原因是什麼? 哪些情況會發生粘包現象?

粘包:資料粘在一起,主要因為:接收方不知道消息之間的界限,不知道一次性提取
多少位元組的資料造成的資料量比較小,時間間隔比較短,就合并成了一個包,
這是底層的一個優化算法(Nagle算法)
      

8,基于socket開發一個聊天程式,實作兩端互相發送和接收消息

  服務端:

# _*_ coding: utf-8 _*_ 
# 8,基于socket開發一個聊天程式,實作兩端互相發送和接收消息
import socket
ip_port = ('127.0.0.1',8088)
link =  socket.socket(socket.AF_INET,socket.SOCK_STREAM)
link.bind(ip_port)
link.listen(5)

print("等待資料連接配接:。。》》")
# 阻塞直到有連接配接為止,有了一個新連接配接進來後,就會為這個請求生成一個連接配接對象
conn, addr = link.accept()

client_data = conn.recv(1024)
print("這是收到的消息:",client_data.decode('utf-8'))
conn.send(client_data.upper())

conn.close()
link.close()

      

用戶端

# _*_ coding: utf-8 _*_ 
# 8,基于socket開發一個聊天程式,實作兩端互相發送和接收消息/
import socket
ip_port = ('127.0.0.1',8088)
link =  socket.socket(socket.AF_INET,socket.SOCK_STREAM)
link.connect(ip_port)

print("開始發送資料")
cmd = input("請輸入:>>").strip()
link.send(cmd.encode('utf-8'))
data = link.recv(1028)
print(data)

link.close()
      

9,基于tcp socket,開發簡單的遠端指令執行程式,允許使用者執行指令,并傳回結果

服務端:

# _*_ coding: utf-8 _*_
# 9,基于tcp socket,開發簡單的遠端指令執行程式,允許使用者執行指令,并傳回結果
import socket
import struct
import subprocess

ip_port = ('127.0.0.1',9999)
sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sk.bind(ip_port)
sk.listen(5)
while True: #連接配接循環
    conn,addr = sk.accept()
    print(conn,addr)
    while True:  #通信循環
        client_data = conn.recv(1024)
        #處理過程
        res = subprocess.Popen(client_data.decode('utf-8'),shell=True,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
        stdout = res.stdout.read()
        stderr = res.stderr.read()
        # 先發報頭(轉成固定長度的bytes類型,那麼怎麼轉呢?就用到了struct子產品)
        length = len(stdout)+len(stderr)
        header = struct.pack('i',length)
        conn.send(header)
        conn.send(stderr)
        conn.send(stdout)
    conn.close()
sk.close()

conn.close()
sk.close()
      
# _*_ coding: utf-8 _*_ 
# 9,基于tcp socket,開發簡單的遠端指令執行程式,允許使用者執行指令,并傳回結果
import socket
import struct

ip_port = ('127.0.0.1',9999)
sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sk.connect(ip_port)
while True:
    cmd = input("請輸入指令:>>").strip()
    if not cmd:continue
    sk.send(cmd.encode('utf-8'))
    header_struct = sk.recv(1024)
    unpack_res = struct.unpack('i',header_struct)
    total_size = unpack_res[0]
    recv_size = 0
    total_data = b''
    while recv_size < total_size:
        recv_data = sk.recv(1024)
        recv_size += len(recv_data)
        total_data += recv_data
    print("傳回的消息:%s"%total_data.decode('gbk'))
sk.close()

      

10,基于tcp協定編寫簡單FTP程式,實作上傳、下載下傳檔案功能,并解決粘包問題

 用戶端

# _*_ coding: utf-8 _*_

import socket
import struct
import json
downlaod_dir = r'D:\檔案傳輸\client\download'

ip_port = ('127.0.0.1',8808)
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(ip_port)
while True:
    cmd = input(">>>").strip()  #get D:\檔案傳輸\server\a.avi
    if not cmd:continue
    phone.send(cmd.encode('utf-8'))
    #接受檔案的内容,以寫的方式打開一個新檔案,接受服務端發來的檔案内容,并寫入用戶端的新檔案
    #第一步,先收報頭的長度,然後解包
    obj = phone.recv(1024)
    header_size = struct.unpack('i',obj)[0]
    #第二部 再收報頭
    header_bytes = phone.recv(header_size)

    #第三部,從報頭中解析除對真實資料的描述資訊
    header_json = header_bytes.decode('utf-8')
    header_dic = json.loads(header_json)
    '''
     header_dic = {
                'filename':filename,  #a.avi
                'md5':'dsdsd',
                'file_size':os.path.getsize(filename)
            }'''
    print(header_dic)
    total_size = header_dic['file_size']
    filename = header_dic['filename']

    #第四步,接受真實的資料
    with open('%s/%s'%(downlaod_dir,filename),'wb') as f:
        recv_size = 0
        # recv_data = b''
        while recv_size <total_size:
            res = phone.recv(1024)
            # recv_data += res
            f.write(res)
            recv_size += len(res)
            print("總大小: %s  \n已經下載下傳大小  :%s"%(total_size,recv_size))

    # print(recv_data.decode('utf-8'))
phone.close()
      

服務端

# _*_ coding: utf-8 _*_
import subprocess
import socket
import struct
import json
import os
share_dir =r'/檔案傳輸/server/share'

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip_port = ('127.0.0.1',8808)
phone.bind(ip_port)
phone.listen(5)
print("starting....")
while True:  #連結循環
    conn,client_addr = phone.accept()
    print(client_addr)
    while True: #通信循環
        try:
            #收指令
            res = conn.recv(1024)   #b'get a.txt'
            if not res :continue
            #解析指令,提取相應的參數
            cmds = res.decode('utf-8').split()
            filename = cmds[1]
            #以讀的方式打開檔案,讀取檔案内容發送給用戶端
            # with open(filename,'rb') as f:
            #     conn.s
              #制定固定長度的報頭
            header_dic = {
                'filename':filename,  #a.avi
                'md5':'dsdsd',
                'file_size':os.path.getsize(r"%s/%s"%(share_dir,filename))
            }
            header_json = json.dumps(header_dic)
            header_bytes = header_json.encode('utf-8')
             #先發送報頭的長度
            conn.send(struct.pack('i',len(header_bytes)))
             #再發報頭
            conn.send(header_bytes)
             #再發真實的資料
            with open('%s/%s'%(share_dir,filename),'rb') as f:
                # conn.send(f.read())
                for line in f:
                    conn.send(line)


        except ConnectionResetError:
            break
    conn.close()
phone.close()
      

函數版本服務端

# _*_ coding: utf-8 _*_ 
import socket
import os
import struct
import pickle

dirname = os.path.dirname(os.path.abspath(__file__))
filepath = os.path.join(dirname, 'share')

def get(cmds,conn):
    filename = cmds[1]
    file_path = os.path.join(filepath, filename)
    if os.path.isfile(file_path):
        header = {
            'filename': filename,
            'md5': 'xxxxxx',
            'file_size': os.path.getsize(file_path)
        }
        header_bytes = pickle.dumps(header)
        conn.send(struct.pack('i', len(header_bytes)))
        conn.send(header_bytes)

        with open(file_path, 'rb') as f:
            for line in f:
                conn.send(line)
    else:
        conn.send(struct.pack('i', 0))

def put(cmds,conn):
    pass

def run():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('127.0.0.1', 8080))
    server.listen(5)
    print('starting...')
    while True:
        conn, client_addr = server.accept()
        print(client_addr)
        while True:
            try:
                res = conn.recv(1024)
                if not res: continue
                cmds = res.decode('utf-8').split()
                if cmds[0] == 'get':
                    get(cmds,conn)
                elif cmds[0] == 'put':
                    put(cmds,conn)
            except ConnectionResetError:
                break
        conn.close()

    server.close()

if __name__ == '__main__':
    run()
      

函數版本用戶端

# _*_ coding: utf-8 _*_ 
import socket
import struct
import pickle
import os

dirname = os.path.dirname(os.path.abspath(__file__))
filepath = os.path.join(dirname,'download')

def get(client):
    obj = client.recv(4)
    header_size = struct.unpack('i', obj)[0]
    if header_size == 0:
        print('檔案不存在')
    else:
        header_types = client.recv(header_size)
        header_dic = pickle.loads(header_types)
        print(header_dic)
        file_size = header_dic['file_size']
        filename = header_dic['filename']

        with open('%s/%s' % (filepath, filename), 'wb') as f:
            recv_size = 0
            while recv_size < file_size:
                res = client.recv(1024)
                f.write(res)
                recv_size += len(res)
                print('總大小:%s 已下載下傳:%s' % (file_size, recv_size))

def put():
    pass

def run():
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    client.connect(('127.0.0.1',8080))
    while True:
        msg = input(">>>:").strip()  # get a.txt
        if not msg:continue
        client.send(msg.encode('utf-8'))

        cmds = msg.split()
        if cmds[0] == 'get':
            get(client)
        elif cmds[0] == 'put':
            put()

    client.close()

if __name__ == '__main__':
    run()
      

面向對象版本服務端

# _*_ coding: utf-8 _*_ 
import socket
import os
import struct
import pickle


class TCPServer:
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    listen_count = 5
    max_recv_bytes = 8192
    coding = 'utf-8'
    allow_reuse_address = False
    # 下載下傳的檔案存放路徑
    down_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'share')
    # 上傳的檔案存放路徑
    upload_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'upload')

    def __init__(self,server_address,bind_and_listen=True):
        self.server_address = server_address
        self.socket = socket.socket(self.address_family,self.socket_type)

        if bind_and_listen:
            try:
                self.server_bind()
                self.server_listen()
            except Exception:
                self.server_close()

    def server_bind(self):
        if self.allow_reuse_address:
            self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        self.socket.bind(self.server_address)

    def server_listen(self):
        self.socket.listen(self.listen_count)

    def server_close(self):
        self.socket.close()

    def server_accept(self):
        return self.socket.accept()

    def conn_close(self,conn):
        conn.close()

    def run(self):
        print('starting...')
        while True:
            self.conn,self.client_addr = self.server_accept()
            print(self.client_addr)
            while True:
                try:
                    res = self.conn.recv(self.max_recv_bytes)
                    if not res:continue
                    cmds = res.decode(self.coding).split()
                    if hasattr(self,cmds[0]):
                        func = getattr(self,cmds[0])
                        func(cmds)
                except Exception:
                    break
            self.conn_close(self.conn)

    def get(self,cmds):
        """ 下載下傳
        1.找到下載下傳的檔案
        2.發送 header_size
        3.發送 header_bytes file_size
        4.讀檔案 rb 發送 send(line)
        5.若檔案不存在,發送0 client提示:檔案不存在
        :param cmds: 下載下傳的檔案 eg:['get','a.txt']
        :return:
        """
        filename = cmds[1]
        file_path = os.path.join(self.down_filepath, filename)
        if os.path.isfile(file_path):
            header = {
                'filename': filename,
                'md5': 'xxxxxx',
                'file_size': os.path.getsize(file_path)
            }
            header_bytes = pickle.dumps(header)
            self.conn.send(struct.pack('i', len(header_bytes)))
            self.conn.send(header_bytes)
            with open(file_path, 'rb') as f:
                for line in f:
                    self.conn.send(line)
        else:
            self.conn.send(struct.pack('i', 0))

    def put(self,cmds):
        """ 上傳
        1.接收4個bytes  得到檔案的 header_size
        2.根據 header_size  得到 header_bytes  header_dic
        3.根據 header_dic  得到 file_size
        3.以寫的形式 打開檔案 f.write()
        :param cmds: 下載下傳的檔案 eg:['put','a.txt']
        :return:
        """
        obj = self.conn.recv(4)
        header_size = struct.unpack('i', obj)[0]
        header_bytes = self.conn.recv(header_size)
        header_dic = pickle.loads(header_bytes)
        print(header_dic)
        file_size = header_dic['file_size']
        filename = header_dic['filename']

        with open('%s/%s' % (self.upload_filepath, filename), 'wb') as f:
            recv_size = 0
            while recv_size < file_size:
                res = self.conn.recv(self.max_recv_bytes)
                f.write(res)
                recv_size += len(res)


tcp_server = TCPServer(('127.0.0.1',8080))
tcp_server.run()
tcp_server.server_close()

服務端
      

面向對象版本用戶端

# _*_ coding: utf-8 _*_ 
import socket
import struct
import pickle
import os


class FTPClient:
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    # 下載下傳的檔案存放路徑
    down_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'download')
    # 上傳的檔案存放路徑
    upload_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'share')
    coding = 'utf-8'
    max_recv_bytes = 8192

    def __init__(self, server_address, connect=True):
        self.server_address = server_address
        self.socket = socket.socket(self.address_family, self.socket_type)
        if connect:
            try:
                self.client_connect()
            except Exception:
                self.client_close()

    def client_connect(self):
        self.socket.connect(self.server_address)

    def client_close(self):
        self.socket.close()

    def run(self):
        while True:
            # get a.txt 下載下傳   put a.txt 上傳
            msg = input(">>>:").strip()
            if not msg: continue
            self.socket.send(msg.encode(self.coding))
            cmds = msg.split()
            if hasattr(self,cmds[0]):
                func = getattr(self,cmds[0])
                func(cmds)

    def get(self, cmds):
        """ 下載下傳
        1.得到 header_size
        2.得到 header_types header_dic
        3.得到 file_size file_name
        4.以寫的形式 打開檔案
        :param cmds: 下載下傳的内容 eg: cmds = ['get','a.txt']
        :return:
        """
        obj = self.socket.recv(4)
        header_size = struct.unpack('i', obj)[0]
        if header_size == 0:
            print('檔案不存在')
        else:
            header_types = self.socket.recv(header_size)
            header_dic = pickle.loads(header_types)
            print(header_dic)
            file_size = header_dic['file_size']
            filename = header_dic['filename']

            with open('%s/%s' % (self.down_filepath, filename), 'wb') as f:
                recv_size = 0
                while recv_size < file_size:
                    res = self.socket.recv(self.max_recv_bytes)
                    f.write(res)
                    recv_size += len(res)
                    print('總大小:%s 已下載下傳:%s' % (file_size, recv_size))
                else:
                    print('下載下傳成功!')

    def put(self, cmds):
        """ 上傳
        1.檢視上傳的檔案是否存在
        2.上傳檔案 header_size
        3.上傳檔案 header_bytes
        4.以讀的形式 打開檔案 send(line)
        :param cmds: 上傳的内容 eg: cmds = ['put','a.txt']
        :return:
        """
        filename = cmds[1]
        file_path = os.path.join(self.upload_filepath, filename)
        if os.path.isfile(file_path):
            file_size = os.path.getsize(file_path)
            header = {
                'filename': os.path.basename(filename),
                'md5': 'xxxxxx',
                'file_size': file_size
            }
            header_bytes = pickle.dumps(header)
            self.socket.send(struct.pack('i', len(header_bytes)))
            self.socket.send(header_bytes)

            with open(file_path, 'rb') as f:
                send_bytes = b''
                for line in f:
                    self.socket.send(line)
                    send_bytes += line
                    print('總大小:%s 已上傳:%s' % (file_size, len(send_bytes)))
                else:
                    print('上傳成功!')
        else:
            print('檔案不存在')


ftp_client = FTPClient(('127.0.0.1',8080))
ftp_client.run()
ftp_client.client_close()

用戶端
      

11,基于udp協定編寫程式,實作功能

 服務端:

# _*_ coding: utf-8 _*_ 
import socket
ip_port = ('127.0.0.1',8808)
udp_server_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udp_server_client.bind(ip_port)
while True:
    conn,addr = udp_server_client.recvfrom(1024)
    print(conn,addr)

    udp_server_client.sendto(conn.upper(),addr)
      

用戶端:

# _*_ coding: utf-8 _*_ 
import socket
ip_port = ('127.0.0.1',8808)
udp_server_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
    cmd = input(">>>>").strip()
    if not cmd:
        continue
    udp_server_client.sendto(cmd.encode('utf-8'),ip_port)
    back_cmd,addr = udp_server_client.recvfrom(1024)
    print(back_cmd.decode('utf-8'))
      

UDP不會發生粘包現象,下面舉例說明

# _*_ coding: utf-8 _*_ 
import socket

ip_port = ('127.0.0.1',8989)
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
client.sendto('hello'.encode('utf-8'),ip_port)
client.sendto('james'.encode('utf-8'),ip_port)
client.close()
      
# _*_ coding: utf-8 _*_ 
import socket

ip_port = ('127.0.0.1',8989)
server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server.bind(ip_port)
res1 = server.recvfrom(5)
print("res1:",res1)
res2 = server.recvfrom(5)
print("res2:",res2)
server.close()
      

12,執行指定的指令,讓用戶端可以檢視服務端的時間

13,執行指定的指令,讓用戶端可以與服務的的時間同步

# _*_ coding: utf-8 _*_ 
import socket
import subprocess
import time

server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))
while True:
    data, client_addr = server.recvfrom(1024)
    print(data, client_addr)
    obj = subprocess.Popen(data.decode('utf-8'),shell=True,  # time 指令在windows 下不能用
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)
    stdout = obj.stdout.read()
    stderr = obj.stderr.read()
    print(stdout+stderr)
    server.sendto(stdout+stderr,client_addr)
    if data.decode('utf-8') == 'time':
        str_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
        # str_time = '2017-01-01 00:00:00'
        server.sendto(str_time.encode('gbk'), client_addr)

server.close()
      
# _*_ coding: utf-8 _*_ 
import socket
import os
import time
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
    msg = input('>>>:').strip()
    client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
    data,server_addr = client.recvfrom(1024)
    print(data.decode('utf-8'),server_addr)
    localtime = time.localtime()
    os.system("date %d-%d-%d" % (localtime.tm_year, localtime.tm_mon, localtime.tm_mday))  # 設定日期
    os.system("time %d:%d:%d.0" % (localtime.tm_hour, localtime.tm_min, localtime.tm_sec))  # 設定時間

client.close()
      

不經一番徹骨寒 怎得梅花撲鼻香

繼續閱讀