python怎么建立socket服务端

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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()

参考技术A 1
首先先建立一个python文件,命名为 socket_server1.py

2
下面是相关的步骤图.

3
先导入相关的模块.并且定义相关的主机及端口.

4
完整的socket_server1.py文件.

5
设置好之后,通过命令提示符测试(进行测试.开始-----运行-----cmd)

6
先使用python 运行下刚刚的那个文件. >>python socket_server1.py

7
客户端直接使用telnet代替测试一下.>>telnet 127.0.0.1 10086

8
然后在服务端的窗口上面会出现相关的客户端信息,在客户端的窗口上面,输入一个字符,服务器端会显示出来,并且客户端上面会返回一个大写的字符。

9
这个就是一个简单的 python的socket的服务器端了。只是测试,没有排错日志

11.网络编程:socket服务端客户端

socket:

  • socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
  • python中使用socket来进行网络连接传输
  •  

    技术分享图片

    由图可知:

    socket中客户端需要进行的操作是:建立,连接,传输数据 ,接收数据,关闭连接

    服务端需要进行的操作是:建立,绑定IP地址和端口,等待连接,接收数据,传输数据 ,关闭连接

     


    服务端:

    • 建立:socket.socket()
    • 绑定端口:bind((‘IP地址‘,端口)),其中地址和端口号是一个 tuple
    • 监听:listen()
    • 接受连接:accept(),返回值是一个连接实例和一个地址,地址是连接过来的客户端地址,而数据操作要利用这个连接实例
    • 传输数据:send(),传输的数据必须是字节流,所以对字符串数据需要使用encode()
    • 接收数据read:recv(x),传输的数据必须是字节流,x是接收的字节数,如果需要转成Unicode,需要使用decode()
    • 关闭连接close:close()

     

    import socket
    server=socket.socket()#建立socket
    
    server.bind((localhost,1234))#绑定
    server.listen()#监听
    print("开始等待。。。")
    conn,addr=server.accept()#接收连接
    print("连接成功")
    data=conn.recv(1024)#接收数据
    print(data.decode())
    conn.send(data)#发送数据
    
    server.close()#关闭连接
    
    
    print("--------------------")

     

    • 上述代码存在一个问题:只能接受一次连接,连接结束后,服务端socket将关闭,更改成不立即关闭能等待下一个连接的:
    #服务器端
    
    import socket
    server = socket.socket()
    server.bind((localhost,1234)) #绑定ip和端口
    server.listen(5) #监听
    
    print("开始等待")
    while True:
        conn, addr = server.accept()
        print(conn, addr)
        print("客户端连接")
        while True:
            data = conn.recv(1024)
            print("recv:",data)
            if not data:
                print("连接断开...")
                break
            conn.send(data)
    
    server.close()

     

     

     


    客户端:

    • 建立:socket.socket()
    • 连接:connect((‘IP地址‘,端口)),其中地址和端口号是一个 tuple
    • 传输数据:send(),传输的数据必须是字节流,所以对字符串数据需要使用encode()
    • 接收数据recv:recv(),传输的数据是字节流,如果需要转成Unicode,需要使用decode()
    • 关闭连接close:close()
    import socket
    client=socket.socket()#建立socket
    client.connect((localhost,1234))#连接
    client.send("你好".encode())#发送数据
    data=client.recv(1024)#接收数据
    print(data.decode())
    
    client.close()#关闭连接
    • 上述代码存在一个问题:只能发送一次数据,发生完数据就会断开连接,改成可以多次发送数据,不自动断开的【前提是服务端能接收多次】:
    import socket
    
    client=socket.socket()
    
    client.connect((localhost,1234))
    while True:
        cmd=input(">>")
        if len(cmd)==0:
            continue
        client.send(cmd.encode())
        cmd_res=client.recv(1024)
        print(cmd_res.decode())
    
    client.close()

    以上是关于python怎么建立socket服务端的主要内容,如果未能解决你的问题,请参考以下文章

    如何在客户端上建立一个Socket与服务器端连接,包括连接的函数?

    Python3中,建立一个socket客户端向服务端发送json数据是报 unknown url type,为啥呢?

    求助,socket中怎么获取系统选择的端口号

    TCP socket调试工具怎么建虚拟接收端

    socket通讯怎么进行的?

    python全程脱产第31天------TCP协议socket