python學習之【16】網絡編程

主題
  • 客戶端/服務器架構
  • 套接字:通訊終點
  • 套接字地址
  • 面向鏈接與無鏈接套接字
  • Python中的網絡編程
  • SOCKET模塊
  • 套接字對象方法
  • TCP/IP客戶端和服務器
  • UDP/IP客戶端和服務器
  • SocketServer模塊
  • Twisted框架介紹
  • 相關模塊

 

 
1.客戶端服務器架構
 
     客戶<---->INTERNET<------->服務器。客戶連上一個預先已知的服務器,提出本身的請求,發送必要的數據,而後就等待服務器返回的數據。
 
2.套接字:通訊終點
     套接字是一種具備"通訊端點"概念的計算機網絡數據結構。網絡化的應用程序在開始任何通信以前都須要建立套接字、就像電話插口同樣,沒有它就會徹底沒辦法通訊。Python只支持AF_UNIX,AF_NETLINK,AF_INET家族,因爲咱們只關心網絡編程因此咱們都只用AF_INET。
 
3.套接字地址
     若是把套接字比做電話接口----------即通訊的最底層結構,那主機與端口就像區號與電話號碼的一對組合。有了電話還不夠,你還要知道你要打電話給誰,往哪打。一個因特網地址由網絡通訊所必須的主機和端口組成,並且另外一端必定要有人聽才能夠。
     合法的端口號範圍爲0~65535,其中,小於1024的端口號爲系統保留端口。
4.面向鏈接與無鏈接套接字
     (1)面向鏈接
               不管使用哪一個地址家族,套接字的類型只有兩種,面向鏈接和無鏈接。面向鏈接便是在通訊前必須創建一條鏈接,就像跟朋友打電話同樣。實現這種鏈接的主要協議就是傳輸控制協議(TCP),要建立TCP套接字就得在建立的時候指定套接字類型爲SOCK_STREAM。TCP套接字採用SOCK_STREAM這個名字體現了它最爲流套接字的特色,因爲這些套接字使用網際協議(ip)來查找網絡中的主機,因此這樣造成的整個系統,通常會有兩個協議(TCP和IP)名的組合來描述,即TCP/IP。
    (2)無鏈接
              即無需鏈接就能夠進行通訊。但這時,數據到達的順序、可靠性及不重複性就沒法保證了。數據是整個發送的,不會像面向鏈接的協議那樣先被拆分紅小塊。
              實現這種鏈接的主要協議就是用戶數據報協議(UDP)。要建立UDP套接字就得在建立的時候指定套接字類型爲SOCK_DGRAM。"datagram"是"數據報"。
 
5.Python中的網絡編程
     咱們將使用Python中的socket模塊,模塊中的socket()函數用來建立套接字。要使用socket.socket()函數來建立套接字,語法以下:
     socket.socket(socket_family,socket_type,protocol=0)
     如前所述,Socket_family  不是 AF_VNIX 就是 AF_INET ,socket_type能夠是SOCK_STREAM或是SOCK_DGRAM,protocol通常不填,默認爲0。
6.SOCKET模塊
     例如建立一個TCP/IP的套接字,你要這樣調用socket.socket()函數:
     tcpSock = socket.socket(socket.AF_INET,socket.SOCKET_STREAM)
     
     UDP/IP的套接字
     udpSock = socket.socket(socket.AF_INET,socket.SOCKET_DGRAM)
因爲socket模塊中有太多的屬性,咱們在這裏可使用 「from module import *」的語句,咱們就把socket模塊裏全部屬性都帶到咱們的命名空間裏了。
     tcpSock = socket(AF_INET,SOCKET_STREAM) 
 
7.套接字對象(內建)方法
            函數                       描述
        服務器端套接字函數
  •  s.bind( )                  綁定地址(主機名,端口號對)到套接字
  •  s.listen( )                 開始TCP監聽
  •  s.accept( )               被動接受TCP客戶端鏈接,(阻塞式)等待鏈接的到來。                    
       客戶端套接字函數
  •  s.connect( )           主動初始化TCP服務器鏈接。
  •  s.connect_ex( )      connect( )擴展版本,出錯時返回錯誤碼,而不是拋出異常。
      公共用途的套接字函數
  •  s,recv( )                接受TCP數據。
  •  s.send( )               發送TCP數據。
  •  s.sendall( )            完整發送TCP數據。
  •  s.recvfrom( )        接受UDP數據。
  •  s.sendto( )           發送UDP數據。
  •  s.getpeername( )  鏈接到當前套接字的遠程的地址(TCP鏈接)
  •  s.getsockname( )   當前套接字的地址。
  •  s.getsockopt( )     返回當前套接字的參數。
  •  s.setsockopt( )     設置指定套接字的參數。
  •  s.close( )              關閉套接字。
     面向模塊的套接字函數
  •  s.setblocking( )    設置套接字的阻塞與非阻塞模式。
  •  s.settimeout( )     設置阻塞套接字操做的超時時間。
  •  s.gettimeout( )     獲得阻塞套接字操做的超時時間。
     面向文件套接字函數
  •  s.fileno( )            套接字文件描述符。
  •  s.makefile( )        建立一個與該套接字關聯的文件對象。
8.TCP/IP客戶端和服務器
     TCP服務器設計僞代碼:
     ss = socket()                    #建立服務器套接字
     ss.bind()                           #把地址綁定到套接字上
     ss.listen()                          #監聽鏈接
     inf_loop:                           #服務器無線循環
          cs = ss.accept()           #接受客戶端鏈接
     comm_loop:                     #通訊循環
          cs.recv()/cs.send()       #對話(接收與發送)
     cs.close()                          #關閉客戶端套接字
     ss.close()                           #關閉服務器套接字(可選)
 
  全部套接字都用socket.socket( )函數來建立。服務器須要"坐在某個端口上"等待請求。因此它們必需要"綁定"到一個本地的地址上。一個簡單的(單線程)服務器會調用accept( )函數等待鏈接的到來。默認狀況下,accept( )函數是阻塞式的,即程序在鏈接到來以前會處於掛起狀態。套接字也支持非阻塞狀態。
     TCP時間戳服務器(tsTserv.py)
建立一個能接受客戶端的消息,在消息前加一個時間戳後返回TCP服務器
 
   
 from socket import *
     from time import ctime
     HOST = ''
     PORT = 21567
     BUFSIZE = 1024
     ADDR = (HOST,PORT)
     
     tcpSerSock = socket(AF_INET,SOCK_STREAM)
     tcpSerSock.bind( ADDR)
     tcpSerSock.listen(5)
     
     while True:
          print 'waiting for connection......'
          tcpCliSock,addr = tcpSerSock.accept( )
          print '......connected from:',addr
          
          while True:
               data = tcpCliSock.recv(BUFSIZ)
               if not data:
                    break
               tcpCliSock.send('[%s]%s' %(ctime(),data))
               tcpCliSock.close( )
    tcpSerSock.close()

 

 
 
建立TCP客戶端
     僞代碼:
     cs = socket( )               #建立客戶端套接字
     cs.connect( )                #嘗試鏈接服務器
     comm_loop:
          cs.send( )/cs.recv( ) #對話(發送/接收)
     cs.close( )                    #關閉客戶端套接字
 
TCP時間戳客戶端(tsTclnt.py)
 
   
 1  from socket import *
 2  
 3      HOST = 'localhost'
 4      PORT = 21567
 5      BUFSIZ = 1024
 6      ADDR = (HOST,PORT)
 7  
 8      tcpCliSock = socket(AF_INET,SOCK_STREAM)
 9      tcpCliSock.connect(ADDR)
10  
11      while True:
12           data = raw_input('>')
13           if not data:
14                break
15           tcpCliSock.send(data)
16           data = tcpCliSock.recv(BUFSIZ)
17           if not data:
18                break
19           print data
20  
21 tcpCliSock.close()

 

 
 
9.UDP/IP客戶端和服務器
 
     UDP時間戳服務器(tsUserv.py)
 
    
 1 from socket import *
 2      from time import ctime
 3      
 4      HOST = ''
 5      PORT = 21567
 6      BUFSIZ = 1024
 7      ADDR = (HOST,PORT)
 8  
 9      udpSerSock = socket(AF_INET,SOCK_DGRAM)
10      udpSerSock.bind(ADDR)
11  
12      while True:
13           print 'waiting for message......'
14           data,addr = udpSerSock.recvfrom(BUFSIZ)
15           udpSerSock.sendto('[%s] %s' % (ctime,data) ,addr)
16           print '......received from and returned to:',addr
17  
18 udpSerSock.close()

 

 
 
建立一個UDP客戶端
 
    
 1 from socket import *
 2      
 3      HOST = 'localhost'
 4      PORT = "21567"
 5      BUFSIZ = 1024
 6      ADDR = (HOST,PORT)
 7  
 8      udpCliSock = socket(AF_INET,SOCK_DGRAM)
 9      
10      while Trus:
11           data = raw_input('>')
12           if not data:
13                break
14           udpCliSock.sendto(data,ADDR)
15           data,ADDR = udpCliSock.recvfrom(BUFSIZ)
16           if not data:
17                break
18           print data
19  
20 udpCliSock.close()

 

 
10.SocketServer模塊
 
     SocketServer 是標準庫中一個高級別的模塊。用於簡化實現網絡客戶端與服務器所需的大量樣板代碼。該模塊中,已經實現了一些可供使用的類。
 
                                                                 SocketServer模塊的類
 
描述
BaseServer 包含服務器核心功能與混合(mix-in)類掛鉤;這個類只用於派生,因此不會生成這個類的實例;能夠考慮使用TCPServer和UDPServer
TCPServer/UDPServer 基本的網絡同步TCP/UDP服務器
UnixStreamServer/UnixDatagramServer 基本的基於文件同步TCP/UDP服務器
ForkingMixIn/ThreadingMixIn 實現了核心的進程化或線程化的功能;做爲混合類,與服務器類一併使用以提供一些異步特性;這個類不會直接實例化。
ThreadingTCPServer/ThreadingUDPServer ThreadingMixIn和TCPServer/UDPServer的組合
BaseRequestHandler 包含處理服務器請求的核心功能,這個類只用於派生,因此不會生成這個類的實例能夠考慮使用StreamRequestHandler 或 DatagramRequestHandler
StreamRequestHandler/DatagramRequestHandler 用於TCP/UDP服務器處理工具
   


建立一個SocketServerTCP服務器
 
在代碼中,先導入咱們的服務器類,而後像以前同樣定義主機常量。主機常量後就是咱們的請求處理器類,而後是啓動代碼。
 
 
例  SocketServer 時間戳TCP服務器(TsTservss.py)
     
   
 from SocketServer import (TCPServer as TCP,StreamRequsetHandler as SRH)
     from time import ctime
 
     HOST = ''
     PORT = 21567
     ADDR = (HOST,PORT)
 
     class MyRequestHandler(SRH):
          def handle(self):
               print '......connected from:',self.client_address
               self.wfile.write('[%s]%s' % (ctime(),self.rfile.readline()))
     
     tcpServ = TCP(ADDR,MyRequestHandler)
     print 'waiting for connection...'
     tcpServ.serve_forever( )
 

 


建立SocketServerTCP客戶端
 
    
 1 from socket import *
 2      
 3      HOST = 'localhost'
 4      PORT = 21567
 5      BUFSIZ = 1024
 6      ADDR = (HOST,PORT)
 7  
 8      while True:
 9           tcpCliSock = socket(AF_INET,SOCK_STREAM)
10           tcpCliSock.connect(ADDR)
11           data = raw_input('>')
12           if not data:
13                break
14           tcpCliSock.send('%s\r\n' %data)
15           data = tcpCliSock.recv(BUFSIZ)
16           if not data:
17                break
18           print data.strip()
19           tcpCliSock.close()
20  

 

 
11.Twisted框架介紹
     Twsited是一個徹底事件驅動的網絡框架。它容許你使用和開發徹底異步的網絡應用程序和協議。須要安裝它,系統中能夠有:網絡協議、線程、安全和認證、聊天/即時通信、數據庫管理、關係數據庫集成、Web/internet、電子郵件、命令行參數、圖形界面集成等。
 
 
建立一個Twisted Reactor TCP服務器
 
     Twsited Reactor事件戳服務器(tsTservTW.py)
 
     from twisted.internet import protocol,reactor
     from time import ctime
 
     PORT = 21567
     
     class TSServProtocol(protocol.Protocol)
 
-----------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
課後題
 
16-1.  套接字,面向鏈接與無鏈接有何區別?
答:socket第二個參數不一樣。面向鏈接即tcp通訊函數爲socket.socket(socket.AF_INET,socket.SOCK_STREAM),UDP通訊函數第二個參數爲SOCK_DGRAM。
16-2.  客戶端/服務器架構。用你本身的語言描述這個架構。並給出幾個例子?
答:服務器在某端口等待客戶端的鏈接。怎麼說呢      client<------------>internet<------------->server
16-3.  套接字。TCP和UDP中,哪種服務器在接受鏈接後,把鏈接交給不一樣的套接字處理與客戶端的通信。
答:TCP。
16-4.  修改TCP(tsTclnt.py)和UDP(tsUclnt.py)客戶端,讓服務器的名字不要在代碼裏寫死,要容許用戶指定一個主機名和端口,只有在兩個值都沒有輸入的時候才使用默認值。
答:修改後的tsTclnt.py
 1 from socket import *
 2 from time import ctime
 3 
 4 
 5 HOST = ''
 6 PORT = 21567
 7 BUFSIZ = 1024
 8 ADDR = (HOST,PORT)
 9 
10 
11 tcpSerSock = socket(AF_INET,SOCK_STREAM)
12 tcpSerSock.bind(ADDR)
13 tcpSerSock.listen(5)
14 
15 
16 while True:
17         print 'waitiing for connection...'
18         tcpCliSock,addr = tcpSerSock.accept()
19         print '...connected from:',addr
20 
21 
22         while True:
23                 data = tcpCliSock.recv(BUFSIZ)
24                 if not data:
25                         break
26                 tcpCliSock.send('[%s] %s' % (ctime(),data))
27 
28 tcpSerSock.close()
29  
30  

 

16-5.  網絡互聯和套接字。找到《python library reference》 示例tcp客戶端/服務器程序,實現它並讓它運行起來。先運行服務器,而後是客戶端。http://www.python.org/doc/current/lib/Socket_Example.html
 
你認爲這個服務器太無聊,決定要修改服務器,讓它能識別如下命令:
 
data     服務器將返回它的當前時間,即time.ctime(time.time())
os        獲得操做系統的信息(os.name)
ls         獲得當前目錄的文件列表
 
作這個做業的時候,你不必定要有網絡------你的機器能夠本身通信。注:在服務器退出後,要清除綁定後才能再次運行,不然有可能得碰到‘端口已經被使用’的錯誤信息,操做系統通常會在5分鐘內清除綁定。因此請耐心等待。
 
服務器端
 1 from socket import *
 2 import time,os
 3 
 4 
 5 HOST = ''
 6 PORT = 21567
 7 BUFSIZ = 1024
 8 ADDR = (HOST,PORT)
 9 
10 
11 tcpSerSock = socket(AF_INET,SOCK_STREAM)
12 tcpSerSock.bind(ADDR)
13 tcpSerSock.listen(5)
14 
15 
16 while True:
17         print 'waitiing for connection...'
18         tcpCliSock,addr = tcpSerSock.accept()
19         print '...connected from:',addr
20 
21         while True:
22                 data = tcpCliSock.recv(BUFSIZ)
23                 data = data.strip()
24                 if not data:
25                         break       
26                 if data == "date":
27                         tcpCliSock.send('%s' % (time.ctime(time.time())))       
28                 elif data == "os":
29                         tcpCliSock.send('%s' % (os.name))               
30                 elif data == "ls":
31                         tcpCliSock.send('%s' % (os.listdir(os.curdir)))               
32                 else:
33                         tcpCliSock.send('[%s] %s' % (time.ctime(),data))
34                                        
35 
36 tcpSerSock.close()

 

 
16-6日期時間服務。使用socket.getservbyname()函數獲得UDP協議中"daytime"服務所對應的端口。請參考getservbyname()函數的文檔,查閱如何使用的詳細語法。如今,寫一個程序發送一個隨便什麼數據過去,等待回答。一旦你收到了服務器的信息,顯示到屏幕上去。
答:服務端
 1 from socket import *
 2 from time import ctime
 3 
 4 
 5 HOST = "localhost"
 6 
 7 PORT = getservbyname("daytime","udp")
 8 
 9 BUFSIZ = 1024
10 
11 ADDR = (HOST,PORT)
12 
13 udpSerSock = socket(AF_INET,SOCK_DGRAM)
14 
15 udpSerSock.bind(ADDR)
16 
17 while True:
18     print "waiting for message..."
19     data,addr = udpSerSock.recvfrom(BUFSIZ)
20     udpSerSock.sendto("[%s]%s" % (ctime(), data),addr)
21     print "...received from and returned to:",addr
22 
23 
24 udpSerSock.close
25  

 

 
客戶端
 1 from socket import *
 2 from time import ctime
 3 
 4 
 5 HOST = "localhost"
 6 PORT = getservbyname("daytime","udp")
 7 
 8 BUFSIZ = 1024
 9 
10 ADDR = (HOST,PORT)
11 
12 udpCliSock = socket(AF_INET,SOCK_DGRAM)
13 
14 
15 while True:
16     data = raw_input(">")
17     if not data:
18         break
19     udpCliSock.sendto(data,ADDR)
20     data,ADDR = udpCliSock.recvfrom(BUFSIZ)
21     if not data:
22         break
23     print data
24 
25 tcpCliSock.close()

 

 
16-7.半雙工聊天。建立一個簡單的半雙工聊天程序。「半雙工」的意思是當建立一個鏈接,服務啓動的時候,只有一我的能夠打字,另外一我的只有在等到消息通知他輸入消息時才能說話。一旦消息發送出去後,要等到有回覆了才能發送下一條消息。一我的是服務端,另外一我的是客戶端。
 
客戶端
from socket import *

HOST = "localhost"
PORT = 23346
BUFSIZ = 1024
ADDR = (HOST,PORT)


tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)


while True:
    data = raw_input("client>")
    if not data:
        continue
    tcpCliSock.send(data)
    while True:
        data = tcpCliSock.recv(BUFSIZ)
        if not data:
            continue
        else:
            print "server>",data
            break

tcpCliSock.close()

 

 
服務端
 1 from socket import *
 2 
 3 HOST = "localhost"
 4 PORT = 23346
 5 BUFSIZ = 1024
 6 ADDR = (HOST,PORT)
 7 
 8 
 9 tcpServSock = socket(AF_INET,SOCK_STREAM)
10 tcpServSock.bind(ADDR)
11 tcpServSock.listen(5)
12 
13 
14 
15 while True:
16     print "waiting for connection..."
17     tcpCliSock,addr = tcpServSock.accept()
18     print "connected from:",addr
19 
20     while True:
21         data = tcpCliSock.recv(BUFSIZ)
22         if not data:
23             continue
24         print "client>",data
25         data = raw_input("server>")
26         tcpCliSock.send(data)
27    
28 tcpServSock.close()
29  

 

---------------------------------------------------------------------
16-8 全雙工聊天。修改你剛纔的程序,改爲全雙工,即兩我的能夠獨立地發送和接收消息。
答:
服務端
 1 #!/usr/bin/env python
 2 #-*- coding:utf-8 -*-
 3 import socket,traceback,os
 4 from threading import *
 5 
 6 host = 'localhost'
 7 port = 51423     #監聽全部的接口
 8 
 9 #接受消息的線程
10 def handlerecv(clientsock):
11     print "New child",currentThread().getName()
12     print "Got connection from",clientsock.getpeername()
13     while True:
14         data = clientsock.recv(4096)
15         if not len(data):
16             break
17         print data
18     clientsock.close()
19 
20 #發送消息的線程
21 def handlesend(clientsock):
22     while True:
23         data = raw_input(">")
24         data = data + "\n";   #加上換行,好看一點。
25         clientsock.sendall(data)
26     #關閉鏈接
27     clientsock.close()
28 
29 #創建套接字
30 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
31 s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
32 s.bind((host,port))
33 s.listen(1)
34 
35 while True:
36     try:
37         clientsock,clientaddr = s.accept()
38     except KeyboardInterrupt:
39         raise
40     except:
41         traceback.print_exc()
42         continue
43 
44     t = Thread(target = handlerecv,args=[clientsock])
45     t.setDaemon(1)
46     t.start()
47 
48     r = Thread(target = handlesend,args=[clientsock])
49     r.setDaemon(1)
50     r.start()
51  
52  
53  
54  

 

客戶端
 
 1 #!/usr/bin/env python
 2 #-*-coding:utf-8-*-
 3 
 4 from socket import *
 5 import sys
 6 from threading import *
 7 
 8 if(len(sys.argv) < 3):
 9     HOST = 'localhost'
10     PORT = 51423
11 else:
12     HOST = sys.argv[1]
13     PORT = int(sys.argv[2])
14 
15 BUFSIZ = 1024
16 ADDR = (HOST,PORT)
17    
18 def handlesend(tcpCliSock):
19     while True:
20         sdata = raw_input('> ')
21         if not sdata:
22             break
23         tcpCliSock.send(sdata)
24 
25     tcpCliSock.close()
26 
27 tcpCliSock = socket(AF_INET,SOCK_STREAM)
28 tcpCliSock.connect(ADDR)
29 
30 #創建發送消息的線程
31 s = Thread(target = handlesend,args=[tcpCliSock])
32 s.setDaemon(1)
33 s.start()
34 
35 while True:
36     rdata = tcpCliSock.recv(BUFSIZ)
37     if not rdata:
38         break
39     print rdata
40 tcpCliSock.close()

 

 
------------------------------------------------------------------
 
16-9----10  多用戶全雙工聊天。再次修改你的程序,把聊天服務改爲支持多用戶版本。(擴展功能多人,多房間,多線程,全雙工)
 
服務端  cs.py
 1 #!/usr/bin/env python
 2 # _*_ coding: utf8 _*_
 3 
 4 from socket import *
 5 from time import ctime
 6 import threading
 7 from string import split
 8 
 9 HOST = ''
10 PORT = 21567
11 BUFSIZE = 1024
12 ADDR = (HOST, PORT)
13 
14 def Deal(sck, username, room):
15     while True:
16         data = sck.recv(BUFSIZE)
17         for i in  clients[room].iterkeys():
18             if i <> username:
19                 if data <> "quit":
20                     clients[room][i].send("[%s] %s: %s" %(ctime(), username, data))
21                 else:
22                     clients[room][i].send("用戶%s在%s退出房間%s" %(username, ctime(), room ))
23         if data == "quit":
24             del clients[room][username]
25             sck.send(data)
26             sck.close()
27             break
28             
29 
30 chatSerSock = socket(AF_INET, SOCK_STREAM)
31 chatSerSock.bind(ADDR)
32 chatSerSock.listen(5)
33 
34 clients = {"":{},}
35 
36 while True:
37     print 'waiting for connection...'
38     chatCliSock, addr = chatSerSock.accept()
39     print "...connected romt: ", addr
40     data = chatCliSock.recv(BUFSIZE)
41     username, room = split(data)
42     print username
43     if not clients.has_key(room):
44         clients[room] = {}
45     if clients[room].has_key(username):
46         chatCliSock.send("reuse")
47         chatCliSock.close()
48     else:
49         chatCliSock.send("success")
50         clients[room][username] = chatCliSock
51         t = threading.Thread(target=Deal, args=(chatCliSock, username, room))
52         t.start()
53 
54 chatSerSock.close()

 

 

 

客戶端  cc.pyhtml

 1 #!/usr/bin/env python
 2 # _*_ coding: utf8 _*_
 3 
 4 from socket import *
 5 from time import ctime
 6 import threading
 7 import random
 8 from sys import argv, exit, stdout
 9 from getopt import gnu_getopt, GetoptError
10 
11 
12 
13 
14 help_info = ["cs.py [ -h | --help | -u | --username] username",
15     "\t-h or --help\t顯示幫助信息",
16     "\t-u or --username\指定用戶名",
17     "\t-r or --room\t指定房間"]
18 def help():
19     for i in help_info:
20         print i
21 
22 
23 
24 def Send(sck, test):
25     while True:
26         data = raw_input('>')
27         sck.send(data)
28         if  data == "quit":
29             break
30 def Recieve(sck, test):
31     while True:
32         data = sck.recv(BUFSIZ)
33         if data == "quit":
34             sck.close()
35             break
36         str = "\n" + data + "\n>"
37         stdout.write(str)
38 
39 HOST = 'localhost'
40 PORT= 21567
41 BUFSIZ = 1024
42 ADDR = (HOST, PORT)
43 threads = []
44 
45 if __name__ == "__main__":
46     # 解析命令行參數
47     try:
48         opts, args = gnu_getopt(argv[1:], "hu:r:", ["help", "username=", "room="])     
49     except GetoptError, err:
50         print str(err)
51         help()
52         exit(2)
53     username = ""
54     room = ""
55     for o, a in opts:
56         if o in ("-h", "--help"):
57             help()
58             exit(0)
59         elif o in ("-u", "--username"):
60             username = a
61         elif o in ("-r", "--room"):
62             room = a
63         else:
64             print "未知選項"
65             help()
66             exit(2)
67     if not username or not room:
68         help()
69         exit(2)
70     chatCliSock = socket(AF_INET, SOCK_STREAM)
71     chatCliSock.connect(ADDR)
72     chatCliSock.send("%s %s" %(username, room))
73     data = chatCliSock.recv(BUFSIZ)
74     if data == "reuse":
75         print "用戶%s已登陸房間%s" %(username, room)
76         raw_input()
77         exit(1)
78     elif data == "success":
79         print "用戶%s成功登陸房間%s" %(username, room)
80         t = threading.Thread(target=Send, args = (chatCliSock, None))
81         threads.append(t)
82         t = threading.Thread(target=Recieve, args = (chatCliSock, None))
83         threads.append(t)
84         for i in range(len(threads)):
85             threads[i].start()
86         threads[0].join()
相關文章
相關標籤/搜索