古詩詞大全網 - 團隊口號 - python怎麽建立socket服務端

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)

#更多的方法及鏈接請訪問

#?Echo?server?program

from?socket?import?*

import?sys

import?threading

from?time?import?ctime

from?time?import?localtime

import?traceback

import?time

import?subprocess

reload(sys)

sys.setdefaultencoding("utf8")

HOST='127.0.0.1'

PORT=8555?#設置偵聽端口

BUFSIZ=1024

class?TcpServer():

def?__init__(self):

self.ADDR=(HOST,?PORT)

try:

self.sock=socket(AF_INET,?SOCK_STREAM)

print?'%d?is?open'?%?PORT

self.sock.bind(self.ADDR)

self.sock.listen(5)

#設置退出條件

self.STOP_CHAT=False

#?所有監聽的客戶端

self.clients?=?{}

self.thrs?=?{}

self.stops?=?[]

except?Exception,e:

print?"%d?is?down"?%?PORT

return?False

def?IsOpen(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?'%d?is?open'?%?port

return?True

except:

print?'%d?is?down'?%?port

return?False

def?listen_client(self):

while?not?self.STOP_CHAT:

print(u'等待接入,偵聽端口:%d'?%?(PORT))

self.tcpClientSock,?self.addr=self.sock.accept()

print(u'接受連接,客戶端地址:',self.addr)

address?=?self.addr

#將建立的client?socket鏈接放到列表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)

def?readmsg(self,address):

#如果地址不存在,則返回False

if?address?not?in?self.clients:

return?False

#得到發送消息的client?socket

client?=?self.clients[address]

while?True:

try:

#獲取到消息內容data

data=client.recv(BUFSIZ)

except:

print(e)

self.close_client(address)

break

if?not?data:

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'))

#將獲得的消息分發給鏈接中的client?socket

for?k?in?self.clients:

self.clients[k].send(s.encode('utf8'))

self.clients[k].sendall('sendall:'+s.encode('utf8'))

print?str(k)

print([stime],?':',?data.decode('utf8'))

#如果輸入quit(忽略大小寫),則程序退出

STOP_CHAT=(data.decode('utf8').upper()=="QUIT")

if?STOP_CHAT:

print?"quit"

self.close_client(address)

print?"already?quit"

break

def?close_client(self,address):

try:

client?=?self.clients.pop(address)

self.stops.append(address)

client.close()

for?k?in?self.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?-*-

from?socket?import?*

import?sys

import?threading

import?time

reload(sys)

sys.setdefaultencoding("utf8")

#測試,連接本機

HOST='127.0.0.1'

#設置偵聽端口

PORT=8555

BUFSIZ=1024

class?TcpClient:

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()

def?sendmsg(self):

#循環發送聊天消息,如果socket連接存在則壹直循環,發送quit時關閉鏈接

while?self.client.connect_ex(self.ADDR):

data=raw_input('>:')

if?not?data:

break

self.client.send(data.encode('utf8'))

print(u'發送信息到%s:%s'?%(self.HOST,data))

if?data.upper()=="QUIT":

self.client.close()

print?u"已關閉"

break

def?recvmsg(self):

#接收消息,如果鏈接壹直存在,則持續監聽接收消息

try:

while?self.client.connect_ex(self.ADDR):

data=self.client.recv(self.BUFSIZ)

print(u'從%s收到信息:%s'?%(self.HOST,data.decode('utf8')))

except?Exception,e:

print?str(e)

if?__name__?==?'__main__':

client=TcpClient()

client.sendmsg()

UDP版本:

socket-udp-server.py

#?-*-?coding:utf8?-*-

import?sys

import?time

import?traceback

import?threading

reload(sys)

sys.setdefaultencoding('utf-8')

import?socket

import?traceback

HOST?=?"127.0.0.1"

PORT?=?9555

CHECK_PERIOD?=?20

CHECK_TIMEOUT?=?15

class?UdpServer(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()

except?Exception,e:

traceback.print_exc()

return?False

def?listen_client(self):

while?True:

time.sleep(0.5)

print?"hohohohohoo"

try:

recvData,address?=?self.sock.recvfrom(2048)

if?not?recvData:

self.close_client(address)

break

if?address?in?self.clients:

senddata?=?u"%s發送給我的信息是:%s"?%(str(address),recvData.decode('utf8'))

if?recvData.upper()?==?"QUIT":

self.close_client(address)

if?recvData?==?"HEARTBEAT":

self.heartbeat(address)

continue

else:

self.clients.append(address)

senddata?=?u"%s發送給我的信息是:%s"?%(str(address),u'進入了聊天室')

for?c?in?self.clients:

try:

self.sock.sendto(senddata,c)

except?Exception,e:

print?str(e)

self.close_client(c)

except?Exception,e:

#?traceback.print_exc()

print?str(e)

pass

def?heartbeat(self,address):

self.beats[address]?=?time.time()

def?checkheartbeat(self):

while?True:

print?"checkheartbeat"

print?self.beats

try:

for?c?in?self.clients:

print?time.time()

print?self.beats[c]

if?self.beats[c]?+?CHECK_TIMEOUT?<time.time():

print?u"%s心跳超時,連接已經斷開"?%str(c)

self.close_client(c)

else:

print?u"checkp%s,沒有斷開"?%str(c)

except?Exception,e:

traceback.print_exc()

print?str(e)

pass

time.sleep(CHECK_PERIOD)

def?close_client(self,address):

try:

if?address?in?self.clients:

self.clients.remove(address)

if?self.beats.has_key(address):

del?self.beats[address]

print?self.clients

for?c?in?self.clients:

self.sock.sendto(u'%s已經離開了'?%?str(address),c)

print(str(address)+u'已經退出')

except?Exception,e:

print?str(e)

raise

if?__name__?==?"__main__":

udpServer?=?UdpServer()

udpServer.listen_client()

——————————華麗的分割線——————————

socket-udp-client.py:

#?-*-?coding:utf8?-*-

import?sys

import?threading

import?time

reload(sys)

sys.setdefaultencoding('utf-8')

import?socket

HOST?=?"127.0.0.1"

PORT?=?9555

#BEAT_PORT?=?43278

BEAT_PERIOD?=?5

class?UdpClient(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()

def?sendmsg(self):

while?True:

data?=?raw_input(">:")

if?not?data:

break

self.clientsock.sendto(data.encode('utf-8'),self.ADDR)

if?data.upper()?==?'QUIT':

self.clientsock.close()

break

def?heartbeat(self):

while?True:

self.clientsock.sendto('HEARTBEAT',self.ADDR)

time.sleep(BEAT_PERIOD)

def?recvmsg(self):

while?True:

recvData,addr?=?self.clientsock.recvfrom(1024)

if?not?recvData:

break

print(u'從%s收到信息:%s'?%(self.HOST,recvData.decode('utf8')))

if?__name__?==?"__main__":

udpClient?=?UdpClient()

udpClient.sendmsg()