1. 程式人生 > >《Python核心程式設計》第16章 網路程式設計 練習

《Python核心程式設計》第16章 網路程式設計 練習

16-4. 客戶。

修改TCP(tsTclnt.py)和UDP(tsUclnt.py)客戶端,讓伺服器的名字不要在程式碼裡寫死,要允許使用者指定一個主機名和埠,只有在兩個值都沒有輸入的時候,才使用預設值。

# coding=utf-8
__author__ = 'Ibuki Suika'

from socket import *
from time import ctime

HOST = ''
PORT = 21567
BUF_SIZE = 1024
ADDRESS = (HOST, PORT)

server = socket(AF_INET, SOCK_STREAM)
server.bind(ADDRESS)
server.listen(5)

while True:
    print("waiting for connection...")
    sock, address = server.accept()
    print("...connected from: (%s, %d)" % address)
    while True:
        data = sock.recv(BUF_SIZE)
        if data == "end":
            break
        sock.send("[{0:s}] {1:s}".format(ctime(), data))
    sock.close()
server.close()
# coding=utf-8
__author__ = 'Ibuki Suika'

from socket import *

BUF_SIZE = 1024
host = raw_input('host: ')
port = raw_input('port: ')
if host == '':
    host = '127.0.0.1'
if port == '':
    port = '21567'
address = (host, int(port))

client = socket(AF_INET, SOCK_STREAM)
client.connect(address)
while True:
    data = raw_input('>')
    if not data:
        break
    client.send(data)
    s = client.recv(BUF_SIZE)
    if not s:
        break
    print s
client.close()

# coding=utf-8
__author__ = 'Ibuki Suika'

from socket import *
from time import ctime

HOST = ''
PORT = 21567
BUF_SIZE = 1024
ADDRESS = (HOST, PORT)

server = socket(AF_INET, SOCK_DGRAM)
server.bind(ADDRESS)
while True:
    print("waiting for message...")
    data, address = server.recvfrom(BUF_SIZE)
    server.sendto("[%s] %s" % (ctime(), data), address)
    print("...receoved from and returned to:(%s, %d)" % address)
server.close()

# coding=utf-8
__author__ = 'Ibuki Suika'

from socket import *

BUF_SIZE = 1024
host = raw_input('host: ')
port = raw_input('port: ')
if host == '':
    host = '127.0.0.1'
if port == '':
    port = '21567'
address = (host, int(port))

client = socket(AF_INET, SOCK_DGRAM)
while True:
    data = raw_input('>')
    if not data:
        break
    client.sendto(data, address)
    data, address = client.recvfrom(BUF_SIZE)
    if not data:
        break
    print data
client.close()
16–5. Intenet 網路和套接字。

找到Python Library Reference 中7.2.2 節Guido van Rossum的示例TCP 客戶/伺服器程式,實現它並讓它執行起來。先執行伺服器,然後是客戶端。原始碼的一個線上版本可以在這裡找到:

http://www.python.org/doc/current/lib/ Socket_Example.html
你認為這個伺服器太無聊了,決定要修改伺服器,讓它能識別以下命令:

date 伺服器將返回它的當前時間 i.e., time.ctime(time.time())

os    得到作業系統的資訊(os.name)

ls 得到當前目錄的檔案列表 (提示: os.listdir()可以得到目錄列表,os.curdir 能得到當前目錄)

附加題: 要能接受“ls dir”指令,並返回dir 目錄的檔案列表。

做這個作業的時候,你不一定要有網路——你的機器可以跟自己通訊。注:在伺服器退出後,要清除繫結後才能再次執行。否則,有可能得碰到“埠已經被使用”(“port already bound”)的錯誤資訊。作業系統一般會在5 分鐘內清除繫結。所以,請耐心等待。

# coding=utf-8
__author__ = 'Ibuki Suika'

from socket import *
from time import ctime
import os

HOST = ''
PORT = 50007
server = socket(AF_INET, SOCK_STREAM)
server.bind((HOST, PORT))
server.listen(1)
conn, addr = server.accept()
print 'Connected by', addr
while True:
    data = conn.recv(1024)
    if data == "date":
        data = "%s" % ctime()
    elif data == "os":
        data = os.name
    elif data == "ls":
        data = "%s" % os.listdir(os.curdir)
    else:
        break
    conn.sendall(data)
conn.close()
# coding=utf-8
__author__ = 'Ibuki Suika'

from socket import *

HOST = "127.0.0.1"
PORT = 50007
conn = socket(AF_INET, SOCK_STREAM)
conn.connect((HOST, PORT))
while True:
    data = raw_input('>')
    if data == ":q":
        break
    conn.sendall(data)
    data = conn.recv(1024)
    if not data:
        break
    print(data)
conn.close()

16-6. 日期時間服務。

使用socket.getservbyname()函式得到UDP 協議中,“daytime”服務所對應的埠。請參考getservbyname() 函式的文件, 查閱詳細的語法(即:socket.getservbyname.__doc__)。現在,寫一個程式傳送一個隨便什麼資料過去,等待回答。一旦你收到了伺服器的資訊,顯示到螢幕上。

# coding=utf-8
__author__ = 'Ibuki Suika'

from socket import *

port = getservbyname("daytime", "UDP")
addr = ("127.0.0.1", port)
conn = socket(AF_INET, SOCK_DGRAM)
conn.sendto("something", addr)
data, addr = conn.recvfrom(1024)
if data:
    print data
conn.close()

16-7. 半雙工聊天。

建立一個簡單的,半雙工的聊天程式。“半雙工”的意思是當建立一個連線,服務啟動的時候,只有一個人可以打字,另一個人只有在等到有訊息通知他輸入訊息時,才能說話。一旦訊息傳送出去後,要等到有回覆了才能傳送下一條訊息。一個人是服務端,另一個人是客戶端。

# coding=utf-8
__author__ = 'Ibuki Suika'

from socket import *

HOST = ''
PORT = 50007
server = socket(AF_INET, SOCK_STREAM)
server.bind((HOST, PORT))
server.listen(1)
conn, addr = server.accept()
print 'Connected by:', addr
while True:
    data = conn.recv(1024)
    if not data:
        break
    print addr, ": ", data
    data = raw_input('>')
    if data == ':q':
        break
    conn.sendall(data)
conn.close()
# coding=utf-8
__author__ = 'Ibuki Suika'

from socket import *

HOST = '127.0.0.1'
PORT = 50007
conn = socket(AF_INET, SOCK_STREAM)
conn.connect((HOST, PORT))
while True:
    data = raw_input('>')
    if data == ':q':
        break
    conn.sendall(data)
    data = conn.recv(1024)
    if not data:
        break
    print  conn.getpeername(),  ': ', data
conn.close()

16-8. 全雙工聊天。

修改你剛才的程式,改成全雙工,即兩個人可以獨立地傳送和接收訊息。

# coding=utf-8
__author__ = 'Ibuki Suika'

from Tkinter import *
from ttk import *
from socket import *
from select import select
from threading import Thread
from time import ctime


class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.master.title('Python版聊天程式')
        self.frm1 = Frame()
        self.frm1.pack(fill=BOTH)
        self.frm2 = Frame()
        self.frm2.pack(side=BOTTOM, fill=X)
        self.txt = Listbox(self.frm1, width=100, height=20)
        self.txt.pack(side=LEFT, fill=X)
        self.bar = Scrollbar(self.frm1)
        self.bar.pack(side=RIGHT, fill=Y)
        self.txt['yscrollcommand'] = self.bar.set
        self.bar['command'] = self.txt.yview
        self. lbl = Label(self.frm2, text='待發送:')
        self.lbl.pack(side=LEFT)
        self.content = StringVar()
        self.entry = Entry(self.frm2, width=80, textvariable=self.content)
        self.entry.pack(side=LEFT)
        self.btn = Button(self.frm2, text='傳送', command=self.send_msg)
        self.btn.pack(side=LEFT)

    def send_msg(self):
        pass


class ServerApp(App):
    def __init__(self, host, port):
        App.__init__(self)
        self.server = socket(AF_INET, SOCK_STREAM)
        self.server.setblocking(False)
        self.server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        self.server.bind((host, port))
        self.server.listen(1)
        self.inputs = [self.server]
        t = Thread(target=self.server_loop)
        t.setDaemon(True)
        t.start()

    def __del__(self):
        self.conn.close()

    def send_msg(self):
        s = self.content.get()
        self.txt.insert(END, '[%s] me:' % ctime())
        self.txt.insert(END, s)
        self.content.set('')
        if len(self.inputs) == 2:
            self.inputs[1].send(s)

    def server_loop(self):
        while True:
            readers, writers, exceptions = select(self.inputs, [], [])
            for reader in readers:
                if reader is self.server:
                    conn, addr = reader.accept()
                    conn.setblocking(False)
                    self.inputs.append(conn)
                else:
                    data = reader.recv(1024)
                    if data:
                        self.txt.insert(END, '[%s] stranger:' % ctime())
                        self.txt.insert(END, data)
                    else:
                        self.inputs.remove(reader)

if __name__ == '__main__':
    app = ServerApp('', 50007)
    app.mainloop()
# coding=utf-8
__author__ = 'Ibuki Suika'

from Tkinter import *
from ttk import *
from socket import *
from select import select
from threading import Thread
from time import ctime


class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.master.title('Python版聊天程式')
        self.frm1 = Frame()
        self.frm1.pack(fill=BOTH)
        self.frm2 = Frame()
        self.frm2.pack(side=BOTTOM, fill=X)
        self.txt = Listbox(self.frm1, width=100, height=20)
        self.txt.pack(side=LEFT, fill=X)
        self.bar = Scrollbar(self.frm1)
        self.bar.pack(side=RIGHT, fill=Y)
        self.txt['yscrollcommand'] = self.bar.set
        self.bar['command'] = self.txt.yview
        self. lbl = Label(self.frm2, text='待發送:')
        self.lbl.pack(side=LEFT)
        self.content = StringVar()
        self.entry = Entry(self.frm2, width=80, textvariable=self.content)
        self.entry.pack(side=LEFT)
        self.btn = Button(self.frm2, text='傳送', command=self.send_msg)
        self.btn.pack(side=LEFT)

    def send_msg(self):
        pass


class ClientApp(App):
    def __init__(self, host, port):
        App.__init__(self)
        self.conn = socket(AF_INET, SOCK_STREAM)
        try:
            self.conn.connect((host, port))
            self.conn.setblocking(False)
        except error:
            self.txt.insert(END, '連線伺服器失敗')
        else:
            t = Thread(target=self.recv_msg_loop)
            t.setDaemon(True)
            t.start()

    def __del__(self):
        self.conn.close()

    def send_msg(self):
        s = self.content.get()
        self.txt.insert(END, '[%s] me:' % ctime())
        self.txt.insert(END, s)
        self.content.set('')
        self.conn.send(s)

    def recv_msg_loop(self):
        while True:
            readers, writers, exceptions = select([self.conn], [], [])
            if len(readers) > 0:
                s = self.conn.recv(1024)
                if s:
                    self.txt.insert(END, '[%s] stranger:' % ctime())
                    self.txt.insert(END, s)
                else:
                    break


if __name__ == '__main__':
    app = ClientApp('127.0.0.1', 50007)
    app.mainloop()

16-9. 多使用者全雙工聊天。

再次修改你的程式,把聊天服務改成支援多使用者版本。

# coding=utf-8
__author__ = 'Ibuki Suika'

#尚未完成

from Tkinter import *
from ttk import *
from socket import *
from select import select
from threading import Thread
from time import ctime


class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.master.title('多人聊天程式')
        self.frm1 = Frame()
        self.frm1.pack(fill=BOTH)
        self.frm2 = Frame()
        self.frm2.pack(side=BOTTOM, fill=X)
        self.frm3 = Frame()
        self.frm3.pack(side=BOTTOM, fill=X)
        self.txt = Listbox(self.frm1, width=105, height=20)
        self.txt.pack(side=LEFT, fill=X)
        self.bar = Scrollbar(self.frm1)
        self.bar.pack(side=RIGHT, fill=Y)
        self.txt['yscrollcommand'] = self.bar.set
        self.bar['command'] = self.txt.yview
        self. lbl = Label(self.frm2, text='待發送:')
        self.lbl.pack(side=LEFT)
        self.content = StringVar()
        self.entry = Entry(self.frm2, width=60, textvariable=self.content)
        self.entry.pack(side=LEFT)
        self.lbl_0 = Label(self.frm2, text='傳送往:')
        self.lbl_0.pack(side=LEFT)
        self.cb_content = StringVar()
        self.cb_list = []
        self.cb = Combobox(self.frm2,  width=15, textvariable=self.cb_content, state='readonly', values=self.cb_list)
        self.cb.pack(side=LEFT)
        self.btn = Button(self.frm2, text='傳送', command=self.send_msg)
        self.btn.pack(side=LEFT)
        self.lb1_1 = Label(self.frm3, text='IP地址:')
        self.lb1_1.pack(side=LEFT)
        self.ip_content = StringVar()
        self.ip_entry = Entry(self.frm3, width=60, textvariable=self.ip_content)
        self.ip_entry.pack(side=LEFT)
        self.lbl_2 = Label(self.frm3, text='埠號:')
        self.lbl_2.pack(side=LEFT)
        self.port_content = StringVar()
        self.port_entry = Entry(self.frm3, width=18, textvariable=self.port_content)
        self.port_entry.pack(side=LEFT)
        self.connect_btn = Button(self.frm3, text='連線', command=self.connect)
        self.connect_btn.pack(side=LEFT)

    def send_msg(self):
        pass

    def connect(self):
        pass


class ChatApp(App):
    def __init__(self):
        App.__init__(self)
        self.server = socket(AF_INET, SOCK_STREAM)
        self.server.setblocking(False)
        self.server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        self.server.bind(('', 50007))
        self.server.listen(100)
        self.inputs = [self.server]
        t = Thread(target=self.server_loop)
        t.setDaemon(True)
        t.start()

    def __del__(self):
        self.server.close()

    def send_msg(self):
        s = self.content.get()
        self.txt.insert(END, '[%s] me:' % ctime())
        self.txt.insert(END, s)
        self.content.set('')
        if len(self.inputs) == 2:
            self.inputs[1].send(s)

    def server_loop(self):
        while True:
            readers, writers, exceptions = select(self.inputs, [], [])
            for reader in readers:
                if reader is self.server:
                    conn, addr = reader.accept()
                    conn.setblocking(False)
                    self.inputs.append(conn)
                else:
                    data = reader.recv(1024)
                    if data:
                        addr = reader.getpeername()
                        self.txt.insert(END,  '[%s] (%s, %d)' % (ctime(), addr[0], addr[1]))
                        self.txt.insert(END, data)
                    else:
                        self.inputs.remove(reader)

    def connect(self):
        host = self.ip_content.get()
        port = int(self.port_content.get())
        print host, port
        conn = socket(AF_INET, SOCK_STREAM)
        conn.connect((host, port))
        conn.setblocking(False)
        self.inputs.append(conn)
        self.cb_list.append('%s:%d' % (host, port))
        self.cb['values'] = self.cb_list

if __name__ == '__main__':
    app = ChatApp()
    app.mainloop()


相關推薦

Python核心程式設計16 網路程式設計 練習

16-4. 客戶。 修改TCP(tsTclnt.py)和UDP(tsUclnt.py)客戶端,讓伺服器的名字不要在程式碼裡寫死,要允許使用者指定一個主機名和埠,只有在兩個值都沒有輸入的時候,才使用預設值。 # coding=utf-8 __author__ = 'Ibuk

python核心程式設計---讀書筆記:16 網路程式設計

第16章網路程式設計 套接字:用於程序間通訊,或IPC 種類:基於檔案的和基於網路的 地址家族:AF,AddressFamily 兩個程序都執行在同一臺機器,且套接字是基於檔案的 基於網路的套接字:AF_INET,Internet,最廣泛使用 AF_INET6 套接字

python核心程式設計(三版)網路程式設計錯誤修改

//伺服器端程式碼from socket import * from time import ctime host='localhost' port=3330 bufsize = 1024 addr = (host,port) tcpser = socket(AF_INET,SOCK_STREAM)

《c語言從入門到精通》看書筆記——16 網路套接字程式設計(上)——網路

      (1)TCP協議:傳輸協議(TCP)是一種提供克勞資料傳送的通用協議,他是TCP/IP體系結構中傳輸層上的協議。在傳送資料時,應用層的資料傳輸到傳輸層,傢伙是哪個TCP首部,資料就構成了報文。報文就是網路層IP的資料,如果再加上IP首部,就構成了IP資料報。TCP協議的C語言資料描述如下:  

Python十三-網路程式設計

網路程式設計 一、網路程式設計基礎 python 的網路程式設計模組主要支援兩種Internet協議: TCP 和 UDP. 1.1通訊協議 通訊協議也叫網路傳輸協議或簡稱為傳送協議(Communications Protocol),是指計算機通訊或網路裝置的共同語言。 現在最普及的計算機通訊為網路通訊,所以

python學習的32天網路程式設計part2

一、IP和ARP協議(瞭解) 乙太網協議: (1)一組電訊號稱為一組資料報或一組資料幀 (2)但凡接入網際網路的煮雞,必須有一塊獨一無二的網絡卡 (3)所有的資料報都必須分為報頭和資料兩部分。報頭固定18個字元 IP協議: 規定網路地址的協議叫ip協議,它定義的地址稱之為ip地址,廣泛採用的

網路程式設計進階

####一、問答題1、簡述計算機作業系統中的“中斷”的作用? 中斷指當出現需要時,CPU暫時停止當前程式的執行轉而執行處理新情況的程式和執行過程 計算機執行期間,系統內發生任何非尋常的或非預期的急需處理事件,使得cpu暫時中斷當前正在執行的程式而轉去執行相應的事件處理程式。 待處理完畢後又返回原來被中

14 網路程式設計

14.1 幾個網路模組 服務端: import socket s = socket.socket() host = socket.gethostname() port = 8090 s.bind((h

[Python設計模式] 16 上班,幹活,下班,加班——狀態模式

ngs 業務需求 當前時間 finished 過大 大量 封裝 hour abs github地址:https://github.com/cheesezh/python_design_patterns 題目 用代碼模擬一天的工作狀態,上午狀態好,中午想睡覺,下午漸恢復,加班

python核心程式設計練習題答案 (2,3,5,6,7,8,12,13,14,16

#6-2 import random lists=[] for i in range(0,random.randrange(0,101)): n = random.randrange(0,2**31) lists.append(n) while True: try

python核心程式設計

6-1 字串。string模組中是否有一種字串方法或者函式可以鑑定一個字串是否是另一個大字串的一部分? #in/not in 可以判斷一個字串是否再另一個字串中 'bc' in 'abcd' Out[3

Python核心程式設計(十三)--面向物件程式設計

面向物件程式設計主要是類和類的例項 建立類: class MyNewObjectType(bases): 'define MyNewObjectType class' class_suite 關鍵詞是class,緊接著是一個類名,隨後是定義類的類體程式碼 o

Python核心程式設計 練習

筆者剛剛開始Python的系統學習,所以在程式碼上還無法達到pythonic的水準,很多寫法也都是按照C++的習慣來寫的,希望能有前輩進行交流指導。 歡迎拍磚 9_1 #!/usr/bin/python2 # coding: utf-8 if

Python核心程式設計15正則表示式練習答案

#15-1 識別下列字串:“bat,” “bit,” “but,” “hat,” “hit,” 或 “hut” pattern =  r'[bh][aiu]t,?' #15-2  匹配用一個空格分隔的任意一對單詞,比如,名和姓 pattern = r'\b\w+ \w+\

python核心程式設計-6課後習題答案

6-2. 字串識別符號.修改例 6-1 的 idcheck.py 指令碼,使之可以檢測長度為一的識別符號,並且可以識別 Python 關鍵字,對後一個要求,你可以使用 keyword 模組(特別是 keyword.kelist)來幫你. #coding=utf-8 im

Python核心程式設計 練習7–5

7–5. userpw2.py. 下面的問題和例題7.1 中管理名字-密碼的鍵值對資料的程式有關。 (a)修改那個指令碼,使它能記錄使用者上次的登入日期和時間(用time 模組),並與使用者密碼一起 儲存起來。程式的介面有要求使用者輸入使用者名稱和密碼的提示

Python 核心程式設計練習題

7–1. 字典方法。哪個字典方法可以用來把兩個字典合併到一起?  update def updateDict(): dict1 = {'name': 'John', 'Age': 20} dict2 = {'address': 'Beijing road'}

劍指offer程式設計python實現(16題)合併兩個排序的連結串列

劍指offer程式設計題python實現(第16題)合併兩個排序的連結串列 題目描述 輸入兩個單調遞增的連結串列, 輸出兩個連結串列合成後的連結串列, 當然我們需要合成後的連結串列滿足單調不減規則。 '''題目描述 輸入兩個單調遞增的連結串列, 輸出兩個連結串列合成後的連結串列, 當然我們需

【吳恩達】機器學習16異常檢測以及ex8部分程式設計練習

1.異常檢測 1.1思路簡述 首先是一些沒有標籤的資料進行p(x)建模,就是擬合數據得到一個符合資料規律的p(x),然後根據一個特定的閾值來判斷,是否異常。 1.2具體步驟(假設p(x)符合高斯) 在octave中,我們可以使用hist視覺化直方圖來看資料是否是高斯分

Android程式設計權威指南(2版)—16挑戰練習

16.7挑戰練習:優化照片顯示 (1)新建dialog_photo.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.androi