Pythonsocketudp
① python udp多線程的問題
for out_port in self.output_port:
soc = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
soc.connect(("localhost",out_port))
_output.append(soc)
不要用output_port,用input_port。
你這里是往input_port發送數據,不需要關心自己的port,而是對端的port
② python怎麼建立socket服務端
socket伺服器再細分可分為多種了,tcp,udp,websocket,都是調用socket模塊,但是具體實現起來有一點細微的差別
先給出一個tcp和udp通過socket協議實現的聊天室的例子
python聊天室(python2.7版本):
都是分別運行server.py和client.py,就可以進行通訊了。
TCP版本:
socket-tcp-server.py(服務端):
#-*-encoding:utf-8-*-
#socket.getaddrinfo(host,port,family=0,socktype=0,proto=0,flags=0)
#根據給定的參數host/port,相應的轉換成一個包含用於創建socket對象的五元組,
#參數host為域名,以字元串形式給出代表一個IPV4/IPV6地址或者None.
#參數port如果字元串形式就代表一個服務名,比如「http」"ftp""email"等,或者為數字,或者為None
#參數family為地主族,可以為AF_INET,AF_INET6,AF_UNIX.
#參數socktype可以為SOCK_STREAM(TCP)或者SOCK_DGRAM(UDP)
#參數proto通常為0可以直接忽略
#參數flags為AI_*的組合,比如AI_NUMERICHOST,它會影響函數的返回值
#附註:給參數host,port傳遞None時建立在C基礎,通過傳遞NULL。
#該函數返回一個五元組(family,socktype,proto,canonname,sockaddr),同時第五個參數sockaddr也是一個二元組(address,port)
#更多的方法及鏈接請訪問
#Echoserverprogram
fromsocketimport*
importsys
importthreading
fromtimeimportctime
fromtimeimportlocaltime
importtraceback
importtime
importsubprocess
reload(sys)
sys.setdefaultencoding("utf8")
HOST='127.0.0.1'
PORT=8555#設置偵聽埠
BUFSIZ=1024
classTcpServer():
def__init__(self):
self.ADDR=(HOST,PORT)
try:
self.sock=socket(AF_INET,SOCK_STREAM)
print'%disopen'%PORT
self.sock.bind(self.ADDR)
self.sock.listen(5)
#設置退出條件
self.STOP_CHAT=False
#所有監聽的客戶端
self.clients={}
self.thrs={}
self.stops=[]
exceptException,e:
print"%disdown"%PORT
returnFalse
defIsOpen(ip,port):
s=socket(AF_INET,SOCK_STREAM)
try:
s.connect((ip,int(port)))
#s.shutdown(2)
#利用shutdown()函數使socket雙向數據傳輸變為單向數據傳輸。shutdown()需要一個單獨的參數,
#該參數表示s了如何關閉socket。具體為:0表示禁止將來讀;1表示禁止將來寫;2表示禁止將來讀和寫。
print'%disopen'%port
returnTrue
except:
print'%disdown'%port
returnFalse
deflisten_client(self):
whilenotself.STOP_CHAT:
print(u'等待接入,偵聽埠:%d'%(PORT))
self.tcpClientSock,self.addr=self.sock.accept()
print(u'接受連接,客戶端地址:',self.addr)
address=self.addr
#將建立的clientsocket鏈接放到列表self.clients中
self.clients[address]=self.tcpClientSock
#分別將每個建立的鏈接放入進程中,接收且分發消息
self.thrs[address]=threading.Thread(target=self.readmsg,args=[address])
self.thrs[address].start()
time.sleep(0.5)defreadmsg(self,address):
#如果地址不存在,則返回False
ifaddressnotinself.clients:
returnFalse
#得到發送消息的clientsocket
client=self.clients[address]
whileTrue:
try:
#獲取到消息內容data
data=client.recv(BUFSIZ)
except:
print(e)
self.close_client(address)
break
ifnotdata:
break
#python3使用bytes,所以要進行編碼
#s='%s發送給我的信息是:[%s]%s'%(addr[0],ctime(),data.decode('utf8'))
#對日期進行一下格式化
ISOTIMEFORMAT='%Y-%m-%d%X'
stime=time.strftime(ISOTIMEFORMAT,localtime())
s=u'%s發送給我的信息是:%s'%(str(address),data.decode('utf8'))
#將獲得的消息分發給鏈接中的clientsocket
forkinself.clients:
self.clients[k].send(s.encode('utf8'))
self.clients[k].sendall('sendall:'+s.encode('utf8'))
printstr(k)
print([stime],':',data.decode('utf8'))
#如果輸入quit(忽略大小寫),則程序退出
STOP_CHAT=(data.decode('utf8').upper()=="QUIT")
ifSTOP_CHAT:
print"quit"
self.close_client(address)
print"alreadyquit"
break
defclose_client(self,address):
try:
client=self.clients.pop(address)
self.stops.append(address)
client.close()
forkinself.clients:
self.clients[k].send(str(address)+u"已經離開了")
except:
pass
print(str(address)+u'已經退出')
if__name__=='__main__':
tserver=TcpServer()
tserver.listen_client()
——————————華麗的分割線——————————
socket-tcp-client.py(客戶端):
#-*-encoding:utf-8-*-
fromsocketimport*
importsys
importthreading
importtime
reload(sys)
sys.setdefaultencoding("utf8")
#測試,連接本機
HOST='127.0.0.1'
#設置偵聽埠
PORT=8555
BUFSIZ=1024
classTcpClient:
ADDR=(HOST,PORT)
def__init__(self):
self.HOST=HOST
self.PORT=PORT
self.BUFSIZ=BUFSIZ
#創建socket連接
self.client=socket(AF_INET,SOCK_STREAM)
self.client.connect(self.ADDR)
#起一個線程,監聽接收的信息
self.trecv=threading.Thread(target=self.recvmsg)
self.trecv.start()
defsendmsg(self):
#循環發送聊天消息,如果socket連接存在則一直循環,發送quit時關閉鏈接
whileself.client.connect_ex(self.ADDR):
data=raw_input('>:')
ifnotdata:
break
self.client.send(data.encode('utf8'))
print(u'發送信息到%s:%s'%(self.HOST,data))
ifdata.upper()=="QUIT":
self.client.close()
printu"已關閉"
break
defrecvmsg(self):
#接收消息,如果鏈接一直存在,則持續監聽接收消息
try:
whileself.client.connect_ex(self.ADDR):
data=self.client.recv(self.BUFSIZ)
print(u'從%s收到信息:%s'%(self.HOST,data.decode('utf8')))
exceptException,e:
printstr(e)
if__name__=='__main__':
client=TcpClient()
client.sendmsg()
UDP版本:
socket-udp-server.py
#-*-coding:utf8-*-
importsys
importtime
importtraceback
importthreading
reload(sys)
sys.setdefaultencoding('utf-8')
importsocket
importtraceback
HOST="127.0.0.1"
PORT=9555
CHECK_PERIOD=20
CHECK_TIMEOUT=15
classUdpServer(object):
def__init__(self):
self.clients=[]
self.beats={}
self.ADDR=(HOST,PORT)
try:
self.sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.sock.bind(self.ADDR)#綁定同一個域名下的所有機器
self.beattrs=threading.Thread(target=self.checkheartbeat)
self.beattrs.start()
exceptException,e:
traceback.print_exc()
returnFalse
deflisten_client(self):
whileTrue:
time.sleep(0.5)
print"hohohohohoo"
try:
recvData,address=self.sock.recvfrom(2048)
ifnotrecvData:
self.close_client(address)
break
ifaddressinself.clients:
senddata=u"%s發送給我的信息是:%s"%(str(address),recvData.decode('utf8'))
ifrecvData.upper()=="QUIT":
self.close_client(address)
ifrecvData=="HEARTBEAT":
self.heartbeat(address)
continue
else:
self.clients.append(address)
senddata=u"%s發送給我的信息是:%s"%(str(address),u'進入了聊天室')
forcinself.clients:
try:
self.sock.sendto(senddata,c)
exceptException,e:
printstr(e)
self.close_client(c)
exceptException,e:
#traceback.print_exc()
printstr(e)
pass
defheartbeat(self,address):
self.beats[address]=time.time()
defcheckheartbeat(self):
whileTrue:
print"checkheartbeat"
printself.beats
try:
forcinself.clients:
printtime.time()
printself.beats[c]
ifself.beats[c]+CHECK_TIMEOUT<time.time():
printu"%s心跳超時,連接已經斷開"%str(c)
self.close_client(c)
else:
printu"checkp%s,沒有斷開"%str(c)
exceptException,e:
traceback.print_exc()
printstr(e)
pass
time.sleep(CHECK_PERIOD)
defclose_client(self,address):
try:
ifaddressinself.clients:
self.clients.remove(address)
ifself.beats.has_key(address):
delself.beats[address]
printself.clients
forcinself.clients:
self.sock.sendto(u'%s已經離開了'%str(address),c)
print(str(address)+u'已經退出')
exceptException,e:
printstr(e)
raise
if__name__=="__main__":
udpServer=UdpServer()
udpServer.listen_client()
——————————華麗的分割線——————————
socket-udp-client.py:
#-*-coding:utf8-*-
importsys
importthreading
importtime
reload(sys)
sys.setdefaultencoding('utf-8')
importsocket
HOST="127.0.0.1"
PORT=9555
#BEAT_PORT=43278
BEAT_PERIOD=5
classUdpClient(object):
def__init__(self):
self.clientsock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.HOST=HOST
self.ADDR=(HOST,PORT)
self.clientsock.sendto(u'請求建立鏈接',self.ADDR)
self.recvtrs=threading.Thread(target=self.recvmsg)
self.recvtrs.start()
self.hearttrs=threading.Thread(target=self.heartbeat)
self.hearttrs.start()
defsendmsg(self):
whileTrue:
data=raw_input(">:")
ifnotdata:
break
self.clientsock.sendto(data.encode('utf-8'),self.ADDR)
ifdata.upper()=='QUIT':
self.clientsock.close()
break
defheartbeat(self):
whileTrue:
self.clientsock.sendto('HEARTBEAT',self.ADDR)
time.sleep(BEAT_PERIOD)
defrecvmsg(self):
whileTrue:
recvData,addr=self.clientsock.recvfrom(1024)
ifnotrecvData:
break
print(u'從%s收到信息:%s'%(self.HOST,recvData.decode('utf8')))if__name__=="__main__":
udpClient=UdpClient()
udpClient.sendmsg()
③ python socket 發送udp和tcp的區別
Python中的 list 或者 dict 都可以轉成JSON字元串來發送,接收後再轉回來。 首先 import json然後,把 list 或 dict 轉成 JSON json_string = json.mps(list_or_dict)用socket發送過去,例如 s.sendto(json_string, address) 對方用socket接收...
④ python SocketServer UDP接收forking問題 ,這個錯在哪裡
如果你打算編寫多進程的服務程序,Unix/Linux無疑是正確的選擇。由於Windows沒有fork調用,難道在Windows上無法用Python編寫多進程的程序?
由於Python是跨平台的,自然也應該提供一個跨平台的多進程支持。multiprocessing模塊就是跨平台版本的多進程模塊。
multiprocessing模塊提供了一個Process類來代表一個進程對象,下面的例子演示了啟動一個子進程並等待其結束:
importos
#子進程要執行的代碼
defrun_proc(name):
print'Runchildprocess%s(%s)...'%(name,os.getpid())
if__name__=='__main__':
print'Parentprocess%s.'%os.getpid()
p=Process(target=run_proc,args=('test',))
print'Processwillstart.'
p.start()
p.join()
print'Processend.'
執行結果如下:
Parentprocess928.
Processwillstart.
Runchildprocesstest(929)...
Processend.
創建子進程時,只需要傳入一個執行函數和函數的參數,創建一個Process實例,用start()方法啟動,這樣創建進程比fork()還要簡單。
join()方法可以等待子進程結束後再繼續往下運行,通常用於進程間的同步。
⑤ python設計UDP通信時,recvfrom()中的參數是什麼意思
socket.recvfrom(bufsize[, flags])
Receive data from the socket. The return value is a pair (bytes, address) where bytes is a bytes object
representing the data received and address is the address of the socket
sending the data. See the Unix manual page recv(2) for
the meaning of the optional argument flags; it defaults to zero. (The
format of address depends on the address family — see above.)
recvfrom(1)就是從緩沖區讀一個位元組的數據
⑥ python socket udp編程的小問題
從錯誤代碼an
integer
is
required來看,需要提供一個整形。
要做的是改成
port0
=
21567,而不是
port0
=
』21567『。
希望能幫到你,有疑問請追問!
⑦ 如何用python方法檢測UDP埠
本文實例講述了python檢測遠程udp埠是否打開的方法。分享給大家供大家參考。具體實現方法如下:
復制代碼代碼如下:
import socket
import threading
import time
import struct
import Queue
queue = Queue.Queue()
def udp_sender(ip,port):
try:
ADDR = (ip,port)
sock_udp = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock_udp.sendto("abcd...",ADDR)
sock_udp.close()
except:
pass
def icmp_receiver(ip,port):
icmp = socket.getprotobyname("icmp")
try:
sock_icmp = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
except socket.error, (errno, msg):
if errno == 1:
# Operation not permitted
msg = msg + (
" - Note that ICMP messages can only be sent from processes"
" running as root."
)
raise socket.error(msg)
raise # raise the original error
sock_icmp.settimeout(3)
try:
recPacket,addr = sock_icmp.recvfrom(64)
except:
queue.put(True)
return
icmpHeader = recPacket[20:28]
icmpPort = int(recPacket.encode('hex')[100:104],16)
head_type, code, checksum, packetID, sequence = struct.unpack(
"bbHHh", icmpHeader
)
sock_icmp.close()
if code == 3 and icmpPort == port and addr[0] == ip:
queue.put(False)
return
def checker_udp(ip,port):
thread_udp = threading.Thread(target=udp_sender,args=(ip,port))
thread_icmp = threading.Thread(target=icmp_receiver,args=(ip,port))
thread_udp.daemon= True
thread_icmp.daemon = True
thread_icmp.start()
time.sleep(0.1)
thread_udp.start()
thread_icmp.join()
thread_udp.join()
return queue.get(False)
if __name__ == '__main__':
import sys
print checker_udp(sys.argv[1],int(sys.argv[2]))
希望本文所述對大家的Python程序設計有所幫助。
⑧ Python用UDP模擬QQ問題
這個問題很有意思!我也想了很久。如果大家了解UDP和TCP的區別。很多人會告訴你。TCP協議因為是可靠的!它會驗證信息是否發送到目的地。而且TCP連接和斷開時都會經過看似漫長3次握手。而UDP因為是不可靠的 它沒有驗證機制更沒有什麼握手打招呼!我們聊天肯定希望速度越快越好不要有延時,所以有很多人或許會告訴你UDP比TCP快得多!所以QQ用UPD。 這個從理論上講是對的!但大家忽視了一個客觀因素。也就是TCP的驗證和3次握手到底能用多少時間,這里可以告訴你最多不會超過0.5秒也就是500毫秒 這個速度玩游戲的人都知道很慢了。如果說0.5秒你覺得我估計少了那麼1秒怎麼也夠了吧 對於我們人來說1秒不是眨眼的功夫嗎。所以說以上所說不是QQ使用UDP的原因,起碼不是主要原因。(其實QQ也有驗證機制,只不過這個驗證機制是由應用層其他協議完成的)那麼就要更深一層去探討UDP和TCP 在傳輸上區別了。首先我個人認為最主要是UPD包比TCP包要少12個位元組。12個位元組差距雖然很微小 但量變到一定程度那就有質的變化。現在我們2M寬頻理論256KB 每秒,就算200KB吧 等於1600個位元組 大家可以算這個差距。還有一個更深層原因也就是UDP「素質」很差。TCP就很紳士。 為什麼說UDP素質不高 是因為UDP就像馬路那種見縫插幀的司機 誰也不讓 拼了命往前沖 不管你路上有多擠 更不會去想維持一下次序。TCP就不會!一旦TCP覺得路上擁擠就會自覺降低發送速度 他會努力維護次序。這樣一進一退差距就大了。所以我覺得這才是QQ使用UDP的主要原因!也似乎也符合騰訊一貫作風 呵呵 MSN使用TCP 就要慢一些 不信你可以試試
⑨ python3套接字udp設置接受數據超時
Sometimes,you need to manipulate the default values of certain properties of a socket library, for example, the socket timeout.
設定並獲取默認的套接字超時時間。
1.代碼
1 import socket
2
3
4 def test_socket_timeout():
5 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
6 print("Default socket timeout: %s" % s.gettimeout())
7 # 獲取套接字默認超時時間
8 s.settimeout(100)
9 # 設置超時時間
10 print("Current socket timeout: %s" % s.gettimeout())
11 # 讀取修改後的套接字超時時間
12
13
14 if __name__ == '__main__':
15 test_socket_timeout()
2. AF_INET和SOCK_STREAM解釋
1 # 地址簇
2 # socket.AF_INET IPv4(默認)
3 # socket.AF_INET6 IPv6
4 # socket.AF_UNIX 只能夠用於單一的Unix系統進程間通信
5
6 # socket.SOCK_STREAM(數據流) 提供面向連接的穩定數據傳輸,即TCP/IP協議.多用於資料(如文件)傳送。
3.gettimeout()和settimeout()解釋
1 def gettimeout(self): # real signature unknown; restored from __doc__
2 """
3 gettimeout() -> timeout
4
5 Returns the timeout in seconds (float) associated with socket
6 operations. A timeout of None indicates that timeouts on socket
7 operations are disabled.
8 """
9 return timeout
10
11
12 def settimeout(self, timeout): # real signature unknown; restored from __doc__
13 """
14 settimeout(timeout)
15
16 Set a timeout on socket operations. 'timeout' can be a float,
17 giving in seconds, or None. Setting a timeout of None disables
18 the timeout feature and is equivalent to setblocking(1).
19 Setting a timeout of zero is the same as setblocking(0).
20 """
21 pass
22 # 設置套接字操作的超時期,timeout是一個浮點數,單位是秒。值為None表示沒有超時期。
23 # 一般,超時期應該在剛創建套接字時設置,因為它們可能用於連接的操作(如 client 連接最多等待5s )
4.運行結果
1 Default socket timeout: None
2 Current socket timeout: 100.0
⑩ python中使用socket編程,如何能夠通過UDP傳遞一個列表類型的數據
Python中的 list 或者 dict 都可以轉成JSON字元串來發送,接收後再轉回來。
首先
importjson
然後,把 list 或 dict 轉成 JSON
json_string=json.mps(list_or_dict)
如果你用的是Python3,這里的 json_string 會是 str 類型(即Python2的unicode類型),可能需要編碼一下:
if type(json_string) == six.text_type:
json_string = json_string.encode('UTF-8')
用socket發送過去,例如
s.sendto(json_string,address)
對方用socket接收,例如
json_string,addr=s.recvfrom(2048)
把JSON轉成 list 或 dict
list_or_dict=json.loads(json_string)
下面是個完整的例子:
client.py
#!/usr/bin/envpython
#-*-coding:UTF-8-*-
importsocket
importjson
importsix
address=('127.0.0.1',31500)
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
mylist=[1,2,3,4,5,6,7,8,9,10]
json_string=json.mps(mylist)
iftype(json_string)==six.text_type:
json_string=json_string.encode('UTF-8')
s.sendto(json_string,address)
s.close()
server.py
#!/usr/bin/envpython
#-*-coding:UTF-8-*-
importsocket
importjson
address=('127.0.0.1',31500)
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(address)
json_string,addr=s.recvfrom(2048)
mylist=json.loads(json_string)
print(mylist)
s.close()
請先運行server.py,再運行client.py