• 十九、Python之socket编程


    socket(套接字)就是建立连接,发送,接收。大部分网络协议都是建立在socket之上的,例如:httpftpsmtp等等
        socket用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过‘套接字’向网络发出请求或者应答网络请求,说白了就是一种通信机制。它类似于银行,电信啊这些部分的电话客服部门。你打电话的时候,那边会分配一个人回答你的问题,客服部门就相当于socket的服务器端了,这边呢就相当于客户端了,在和你通话结束前,如果有人在想找和你通话的那个说话,是不可能的,因为你在和他通信,当然客服部门的电话交换机也不会重新分配。
        socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open----->读写write/read----->关闭close”模式来操作。Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读写/IO,打开,关闭)。
    流程拓扑图:
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    SocketServer:同时只能接受1个连接,就算listhen改为5还是只能接受1个连接,另一个客户端如果发送数据只能处于等待状态;只有这个客户端断开连接它才能发送数据给服务端
    Socket服务器端编程主要包括下面几步:
    1.      打开socket
    2.      绑定到一个地址和端口
    3.      侦听进来的连接
    4.      接收数据     
    5.      读写收据
    import socket
    HOST = ''                    #为空代表本机
    PORT = 50007
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)        #打开socket
    s.bind((HOST,PORT))         #2    绑定地址和端口,注意里面接一个元组的参数
    s.listen(1)                          #3    1代表同时只能有1个连接
    while  True:
    conn,addr = s.accept()      #3    s.accept()返回两个变量,conn返回哪个客户端连接过来,addr返回客户端地址
    print 'Connected by',addr
    while 1:
               data = conn.recv(1024)     #4          1024代表1k,是接收的客户端的数据
               if not data:                        #代表客户端已经断开了
               break
               conn.sendall(data.upper())             #5          把收到的数据改成大写又发回去
    conn.close()
    以上代码在Linuxmac下面没有问题,但是在Linux里就需要加个异常处理,
    捕捉socketError异常。
    -----------------------------------------------------------------------------------------------------------------
    Socket客户端编程主要包括下面几步:
    1.打开socket
    2.连接到服务器端的地址和端口
    3.读写收据
    import socket
    HOST = '127.0.0.1'                  
    PORT = 50007
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)       
    s.connect((HOST,PORT))                 #2
     
    while  True:
           msg = input(“>>:”).strip()
           if  len(msg) == 0:continue
    s.sendall(msg)
    data = s.recv(1024)                         #等待服务器的返回,并存储在变量data
    print  ‘Received’,data
    s.close()
     
     
     
     
    SocketServer实现多并发(能支持100个左右,再大了可能就扛不住了):
    有三种方式:分叉,线程,异步IO,下例使用的是线程方式
    服务器端:
    import SocketServer
    class MyTCPHandler(SocketServer,BaseRequistHandler):
      while True:
        def handle(self):                #这个handle函数就是用于处理跟客户端所有的通信
          self.data = self.request.recv(1024).strip()
          print ("{} wrote:".format(self.client_address[0]))
          print (self.data)   
          self.request.sendall(self.data.upper())
     
     
    if __name__ == "__main__":
        HOST,PORT = "localhost",9999  
        server = SocketServer.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
        server.server_forever()
     
    客户端:
    客户端改下端口就行了,对应服务端的9999
     
     
     
     
     
     
     
     
     
     
    SocketServer实现文件传送:目前我们做的是就是客户端发送什么我就给它改成大写返回去,没什么用,这节就是讲让server干点事情
     
    1.客户端发过来的命令我让它执行,模仿puppetsaltstack。。。。。。(但还有很多问题)
    服务器端:
    import SocketServer
    import  os
    class MyTCPHandler(SocketServer,BaseRequistHandler):
    def handle(self):            #这个handle函数就是用于处理跟客户端所有的通信
    while True:
          data = self.request.recv(1024).strip()
               cmd_res = os.popen(data).read()
               if len(cmd_res)==0:
                         cmd_res = “cmd has no feedback”
          self.request.sendall(data.upper())
     
    if __name__ == "__main__":
        HOST,PORT = "localhost",9999  
        server = SocketServer.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
        server.server_forever()
     
     
    客户端:
    import socket
    HOST = '127.0.0.1'                  
    PORT = 9999
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)       
    s.connect((HOST,PORT))                 #2
     
    while  True:
           msg = input(“>>:”).strip()
           if  len(msg) == 0:continue
    s.sendall(msg)
    data = s.recv(8196)                         #等待服务器的返回,并存储在变量data
    print  ‘Received’,data
    s.close()
     
     
     
     
     
     
    SocketServer实现ftp雏形:
     
    服务器端:客户端往服务器上传文件目录recv
    import SocketServer
    import  os
    class MyTCPHandler(SocketServer,BaseRequistHandler):
    def handle(self):                 #这个handle函数就是用于处理跟客户端所有的通信
             while True:
               data = self.request.recv(1024).strip()
                       data=data.split(“|”)
                       if  hasattr(self,data[0]):
                                func=getattr(self,data[0])
                                func(data[1:])
    def  file_transfer(self,msg):
               if msg[0] == “get”:
                       print (“-----going to send file:%s to client ” % msg[1])
                       filename = msg[1]
    if os.path.isfile(filename):                                                                #判断客户端发来的请求是否是文件并且存在
             filesize = os.path.getsize(filename)                                    #1.判断客户端发来的文件的大小
             ack_msg = “file_transfer|get|ready” % file_size            #服务器给客户端的应答(如果文件存在的情况)
             self.request.send(ack_msg)                                                    #执行发送ack_msg给客户端
             client_ack = self.request.recv(1024)                                   
    print ‘-----à client ack:’,client_ack
    if client_ack.startswith(“file_transfer|get|recv|ready”):
             f = file(filename,”rb”)
             for line in f:
                       self.request.send(line)
             else:
                       print ‘--------file %s send done-------’ % filename
                       f.close()
    else:
             ack_msg = “file_transfer|get|file doesn’t exists”           #服务器给客户端的应答(如果文件不存在的情况)
             self.request.send(ack_msg)    
     
     
     
     
    if __name__ == "__main__":
        HOST,PORT = "localhost",9999  
        server = SocketServer.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
        server.server_forever()
     
     
     
    客户端:从服务器端下载文件目录recv
    import socket
    class FTP(object):
       def __init__(self,host,port):
                  self.host = host
                  self.port = port
       def put(self,msg):        #定义上传方法,命令为put  local_file  
       def get(self,msg):        #定义下载方法,命令为get  remote_file
                  print  ‘---->get:’,msg
                  if len(msg) > 0:
                         remote_filename=msg[0]
                         cmd_msg=”file_transfer|get|%s” % remote_filename
                         self.sock.send(cmd_msg)
                         feedback = self.sock.recv(1024)
                         print (‘----->feedback:’,feedback)
                         if feedback.startswith(“file_transfer|get|read”):
                                file_size = int(feedback.split(“|”)[-1])
                                ack_msg = “file_transfer|get|recv|ready”
                                self.sock.send(ack_msg)
                                f = file(“recv/%s” % remote_filename,’wb’)
                                recv_size = 0
                                while not file_size == recv_size:
                                       if file_size  -  recv_size > 1024:
                                              data = self.sock.recv(1024)
                                              f.write(data)
                                              recv_size += len(data)
                                       else:
                                              data = self.sock.recv(file_size – recv_size)
                                              recv_size+= file_size  - recv_size
    f.write(data)              
    else:
           f.close()
           print “-----recv file ”
                                print (feedback)
       def list_file(self):         #定义查看方法
     
       def interactive(self):   #定义交互方法
                  while True:
                         user_input = input(“ftp_client::”).strip()
                         if len(user_input) == 0:continue
                         cmd = user_input.split()
                         if  hasattr(self,cmd[0]):                        #这里用到了反射
                                func = getattr(self,cmd[0])
                                func(cmd[1:])
                         else:
                                print  “Wrong  cmd  usage!”
          
       def connect(self):        #定义连接方法
                  self.sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)         
    self.sock.connect((self.host,self.port))
    self.interactive()
    if  __name__ == ‘__main__’:
       ftp = FTP(192.168.1.130,9999)
     
     
     
     
    HOST = '192.168.1.130'                 
    PORT = 9999
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)       
    s.connect((HOST,PORT))                 #2
     
    while  True:
           msg = input(“>>:”).strip()
           if  len(msg) == 0:continue
    s.sendall(msg)
    data = s.recv(8196)                         #等待服务器的返回,并存储在变量data
    print  ‘Received’,data
    s.close()
     
     
  • 相关阅读:
    解决Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom:2.12.4
    spring task:annotation-driven 定时任务
    Windows注意目录
    vbScript 备忘
    java 将字符串数组变为字典顺序排序后的字符串数组
    jquery选中以什么开头的元素
    java如何将毫秒数转为相应的年月日格式
    jstl foreach 取index
    jQuery 效果
    js判断一个字符串是以某个字符串开头
  • 原文地址:https://www.cnblogs.com/steven9898/p/11329448.html
Copyright © 2020-2023  润新知