python network programming (socket)

A, Socket introduction

  • Socket socket, python standard library provides socket.py, very low-level interface library
  • Socket is a universal network programming interfaces, and network level is not one to one relationship

1, Socket type

  •  SOCK_STREAM: stream-oriented socket connection, the default value, TCP protocol
  •  SOCK_DGRAM: five connected datagram sockets, UDP protocol

Two, TCP programming

  • Socket programming, at both ends, in general, need a server, a client, the server is called Sever, the client called lient

1, TCP server

 Server-side programming steps:

  •  Create a Socket object
  •  Address of the IP address and port Port, bind () method, IPv4 address is a tuple ( 'ip address string', Port)
  •  Start listening, listens on the specified IP port, listen () method
  •  Get Socket object for transmitting data: socket.accept () -> (socket object, address info)
  •  accept method blocked waiting for the client to establish a connection tuple returns a new Socket object and the client's address
  •  Address is the address of the remote client, IPv4 it is a tuple (clientaddr, port)
s = socket.socket () # Create a socket object 
    s.bind (( '127.0.0.1', 8888 )) # a tuple 
    s.listen () # begins listening 

    # open a connection 
    s1, info = s.accept ( ) # blocked until the client a successful connection, a return address and the client socket object 

    # buffer is used to obtain data 
    data = s1.recv (1024 ) 
    Print (data, info) 
    s1.send (b'magedu.com ACK ')

2, write a group chat program

CS is a chat program, C every client, S is the server, the server should have the function of:

  •   Start the service, including the bound address and port, monitor
  •   Establish a connection, the connection can be established and a plurality of clients, different users receive information
  •   Distribution, the user will receive a message forwarded to all clients connected
  •   Stop the service, record client connections, the server should correspond to a class
Examples 
    Import the logging 
    Import Socket 
    Import Threading  Import datetime 
 FORAMT = '% (the asctime) S% (Thread) D% (Message) S' logging.basicConfig (Level = logging.info, the format = FORAMT) class ChatSever: DEF the __init __ (Self, ip = '127.0.0.1', port = 8888): # = start service self.sock socket.socket () self.addr = (IP, Port) self.clients = {} = # client self.event threading.Event () def start (self): # start listening self.sock.bind (self.addr) self.sock.listen () # monitor #accept will block the main thread, so to open a new thread print ( '---- -------- ' ) of the threading.Thread (target = self.accept) .start () DEF Accept (Self): # people connected sock, client = self.sock.accept () # obstructive print (111, sock, client) self.clients [client ] = sock # # dictionary to add to the client is ready to receive data, recv is blocked, open a new thread threading.Thread (target = self.recv, args = (our sock, Client) ) .start () def recv (self , sock: socket, client): # Not receiving client data the while self.event.is_set (): data = sock.recv (1024) to data # blocking incoming msg = "{: the Y% /% m /% D% H:% m:% S} {}: {} \ {n-} \ n-".format (datetime.datetime.now (), * Client, data.decode ()) Print ( 'msg' ) logging.info (msg) in S for self.clients.values (): s.send (msg.encode ()) DEF sTOP (Self): # S in stop service for self.clients.values ( ): S.CLOSE () self.sock.close () self.event.set () CS = ChatSever () cs.start () = E threading.Event () Not e.wait the while (. 1 ): cmd = INPUT ( '>>>' ) .strip () IF cmd == "quit" : cs.stop () E.wait(3) breakClient interrupts the problems caused by the server know when to disconnect yourself, if the client is disconnected, the server does not know it is good practice, the client develop a special message to inform the server is disconnected However, if a customer initiative calls for end, the server sends a blank message, timeout returns an exception, catch the exception and clean-up connection even if the client provides a disconnect command, there is no guarantee the client will use it disconnected, but still want to increase the exit Features
The following is the code to add functionality 
    to increase the client exits order 
    to increase multi-client support 


    Import the logging 
    Import Socket 
    Import Threading  Import datetime 
 FORAMT = '% (the asctime) S% (Thread) D% (Message) S' logging.basicConfig (Level = the logging. INFO, format = FORAMT) class ChatSever: DEF __init __ (Self, ip = '127.0.0.1', Port = 8888): # = start service self.sock socket.socket () self.addr = (ip, Port) Self. clients = {} # = client self.event threading.Event () start DEF (Self): # start listening self.sock.bind (self.addr) self.sock.listen () # will block the main thread monitor #accept , so to open a new thread Print ( '------------' ) threading.Thread (target =self.accept) .start () def accept ( self): # people connected sock, client = self.sock.accept () # blocking Print (111 , our sock, Client) self.clients [Client] # = Add to our sock # client dictionary is ready to receive data, recv is blocked, open a new thread threading.Thread (target = self.recv, args = (our sock, client)) Start () DEF recv. (Self, our sock: socket, client) : # not receiving client data the while self.event.is_set (): the data = sock.recv (1024) # = blocked until data arrives msg data.decode () Strip () # client exits command if msg == ". quit " : self.clients.pop (Client) sock.close () logging.info (" {} quits " .format (Client)) BREAK MSG =" {: the Y% /% m /% D% H:% m :%} {S}: {} \ {n-} \ n-".format (datetime.datetime.now (), * Client, data.decode ()) Print ( 'MSG' ) logging.info (MSG) for S in self.clients.values (): s.send (msg.encode ()) DEF sTOP (Self): # stop service for s in self.clients.values(): s.close() self.sock.close() self.event.set() cs = ChatSever() cs.start() e = threading.Event() while not e.wait(1): cmd = input('>>>').strip() if cmd == "quit": cs.stop() e.wait(3) break

3, other methods

  •  socket.recv (): get the data, the default is blocking the way
  •  socket.recvfrom (): Get data, returns a tuple
  •  socket.recv_info (): After obtaining nbytes data stored in buffer
Create a socket associated with the attached file object 
using makefile group chat rewritable type 


Import the logging 
Import Socket 
Import Threading  Import datetime 
 FORAMT = '% (the asctime) S% (Thread) D% (Message) S' logging.basicConfig (Level logging.info =, format = FORAMT) class ChatSever: DEF __init __ (Self, ip = '127.0.0.1', Port = 8888): # = start service self.sock socket.socket () self.addr = (ip, Port ) self.clients = {} # = client self.event threading.Event () start DEF (Self): # start listening self.sock.bind (self.addr) self.sock.listen () # monitor will #accept block the main thread, so to open a new thread Print ( '------------' ) threading.Thread (target = self.accept) .start () DEF the Accept (Self): # multiplayer while not connectedself.event.is_set (): sock, client = self.sock.accept () # blocking Print (111 , our sock, Client) F = sock.makefile (MODE = 'RW' ) self.clients [Client] = F # Add to Dictionary # client is ready to receive data, recv is blocked, open a new thread threading.Thread (target = self.recv, args = (f, client), name = 'recv' ) .start () DEF recv ( self, f, client): # Not receiving client data the while self.event.is_set (): the try : data = f.readline () # newline to blocking the except Exception AS E: logging.error (E) any # exit exception guarantee = Data 'quit' MSG = data.strip () # client exits == MSG command IF "quit" : self.clients.pop (client) f.close () logging.info ( "{} quits" .format (Client)) BREAK MSG = "{: the Y% /% m /% D% H:% m:% S} {}: {} \ {n-} \ n-" .format (datetime.datetime.now ( ), * Client, Data) Print ( 'MSG') logging.info(msg) for s in self.clients.values(): s.wtitelines(msg) s.flush() def stop(self): #停止服务 for s in self.clients.values(): s.close() self.sock.close() self.event.wait(3) self.event.set() def show_thread(e:threading.Event): while not e.wait(3): logging.info(threading.enumerate()) def main(): e = threading.Event() cs = ChatSever() cs.start() threading.Thread(target=show_thread, args=(e,), name='showthread').start() while not e.wait(1): cmd = input('>>>').strip() if cmd == "quit": cs.stop() e.wait(3) break if __name__ == "__main__": main() Socket太底层了,实际开发中很少使用这么底层的接口 


Three, TCP client

  •  Client programming steps
  •  Create a Socket object
  •  Connect to the remote server ip and port, connect ()
  •  Data transmission: using the send, recv method for receiving data
  •  Close the connection, the release of resources
Import the logging 
Import Socket 
Import Threading 
Import datetime 
 FORAMT = '% (the asctime) S% (Thread) D% (Message) S'  logging.basicConfig (Level = logging.info, the format = FORAMT) class ChatClient: DEF the __init __ (Self, IP = '127.0.0.1', Port = 8888 ): self.sock = socket.socket () self.addr = (IP, Port) self.event = threading.Event () self.start () Start DEF (Self): # initiate the connection to the remote self.sock.connect (self.addr) # ready to receive data, recv is blocked, open a new thread threading.Thread (target = self._recv, name = "recv" ) .start ( ) def _recv (self): # Not receiving client data the while self.event.is_set (): the try : data = self.sock.recv (1024) blocked except # Exception as e: logging.error(e) break msg = "{:%Y/%m/%d %H:%M:%S} {} : {}\n{}\n".format(datetime.datetime.now(), *client, data) logging.info(msg) def send(self, msg:str): data = "{}\n".format(msg.strip()).encode() self.sock.send(data) def stop(self): logging.info("{} broken".format(self.addr)) self.sock.close() self.event.wait(3) self.event.set() logging.info("client stops") def show_thread(e:threading.Event): while not e.wait(3): logging.info(threading.enumerate()) def main(): e = threading.Event() cc = ChatClient() while True: msg = input('>>>') if msg.strip() == "quit": cs.stop() break cc.send(msg) if __name__ == '__main__': main()

 

四、Socketserver

  • underlying socket programming too, although there are routine programming, but it is quite difficult to want to write robust code, so many languages ​​of the socket encapsulates the underlying API, Python module package is socketserver
  • Network services programming framework to facilitate the rapid development of enterprise-class

1 inheritance, classes

  •  SocketSever simplify writing network servers
  •  It has four synchronization classes: TCPServer, UDPServer, UnixStreamServer, UnixDatagramServer
  •  2 ForkingMixln Mixin classes and classes to support asynchronous ThreadMixln

2. Programming Interface

  •  socketserver.BaseServer(sever_address, RequestHandleClass)
  •  Binding requires providing server address information, and a request for handling RequestHandlerClass, RequestHandleClass class must be a subclass of the class BaseRequestHandler

3, BaseRequestHandler class

  •  And user-based user connection request processing, after receiving a user request Server instance, eventually instantiate the class; it is initialized, configured into three parameters: request, client_address, server
  •  Can later on an instance of class BaseRequestHandler
  •  self.request socket target client is connected
  •  self.server itself is TCPserver
  •  self.client_address client address
  •  It will be the first call three functions, a subclass can override
Import Threading 
    Import SocketServer 

    class the MyHandler (of SocketServer.BaseRequestHandler): 
        DEF handle (Self):  Print (self.server, self.request, self.client_address)  Print ( '{} handler'.format (Self class__ is .__ )) Print (Self class__ is .__ ) Print (type (Self) .__ dict__ magic ) Print (Self .__ class __.__ bases __ [0] .__ dict__ magic ) Print (threading.enumerate (), threading.current_thread ()) = addr ( '127.0.0.1', 8888 ) server = the accept the corresponding socketserver.ThreadingTCPServer (addr, MyHandler) server.serve_forever ( ) test results show, handler method and the socket, the user connection request over a socket connection is established and generates self.request object stored in the client address save in self.client_address in

4, create a server requires several steps

  •  Subclass must BaseRequestHandler class and by covering the other handle () method to create a request handler class, this method will process incoming requests
  •  You must instantiate a class server, passing it the address of the server, and the request handler class
  •  Then call the server object handle_request () or server_forever () method
  •  Call server_close () closes the socket, shutdown () method, wait stop server_forever ()

5, to achieve EchoServer

  • As the name suggests, Echo to echo what the message of what the message, sent by the client what information, what information is returned
import threading
import socketserver

class EchoHandler(socketserver.BaseRequestHandler):
    def finish(self):
        super().finish()
        self.event.set()  # 清理工作

    def setup(self):
        super().setup()
        self.event = threading.Event()  # 初始化工作

    def handle(self): super().handle() while not self.event.is_set(): data = self.request.recv(1024).decode() msg = "{} {}".format(self.client_address, data).encode() self.request.send(msg) print('End') addr = ('127.0.0.1', 8888) server = socketserver.ThreadingTCPServer(addr, EchoHandler) server_thread = threading.Thread(target=server.serve_forever, daemon=True) server_thread.start() try: while True: cmd = input('>>>') if cmd.strip() == 'quit': break except Exception as e: print(e) except KeyboardInterrupt: print('Exit') finally: server.shutdown() server.server_close() 

 

Guess you like

Origin www.cnblogs.com/jiangzuofenghua/p/11453886.html