一、socketserver模块说明
- socket并不能多并发,只能支持一个用户,socketserver 简化了编写网络服务程序的任务,socketserver是socket的在封装。socketserver在python2中为SocketServer,在python3种取消了首字母大写,改名为socketserver。
- socketserver内部使用IO多路复用以及“多线程”和“多进程”,从而实现并发处理多个客户端请求的scoket服务端。即,每个客户端请求连接到服务器时,socket服务端都会在服务器是创建一个“线程”或“进程”专门负责处理当前客户端的所有请求。
- socketserver中包含了两种类,一种为服务类(server class),一种为请求处理类(request handle class)。前者提供了许多方法:像绑定,监听,运行…… (也就是建立连接的过程);后者则专注于如何处理用户所发送的数据(也就是事务逻辑)。一般情况下,所有的服务,都是先建立连接,也就是建立一个服务类的实例,然后开始处理用户请求,也就是建立一个请求处理类的实例。
二、server类型介绍
1.5种server类 BaseServer,TCPServer,UnixStreamServer,UDPServer,UnixDatagramServer。 注意:BaseServer不直接对外服务。
- class socketserver.BaseServer:这是模块中的所有服务器对象的超类。包含服务器的核心功能与混合类(min-in)的钩子功能.这个类主用于派生,不要直接生成这个类的类对象,它定义了接口,但是大多数的方法不实现,在子类中进行细化。
- class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True) 支持使用IPV4的TCP协议的服务器,address是一个(host,port)元组.Handler是BaseRequestHandler或StreamRequestHandler类的子类的实例.
- class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True) 支持使用IPV4的UDP协议的服务器,address和handler与TCPServer类似.
- class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True) 使用UNIX域套接字实现面向数据流协议的服务器,继承自TCPServer.
- class socketserver.UnixDatagramServer(server_address, RequestHandlerClass,bind_and_activate=True) 使用UNIX域套接字实现数据报协议的服务器,继承自UDPServer.
2.继承关系
3.BaseServer方法
1 BaseServer.fileno():返回服务器监听套接字的整数文件描述符。通常用来传递给select.select(), 以允许一个进程监视多个服务器。 2 3 BaseServer.handle_request():处理单个请求。处理顺序:get_request(), verify_request(), process_request()。如果用户提供handle()方法抛出异常,将调用服务器的handle_error()方法。如果self.timeout内没有请求收到, 将调用handle_timeout()并返回handle_request()。 4 5 BaseServer.serve_forever(poll_interval=0.5): 处理请求,直到一个明确的shutdown()请求。每poll_interval秒轮询一次shutdown。忽略self.timeout。如果你需要做周期性的任务,建议放置在其他线程。 6 7 BaseServer.shutdown():告诉serve_forever()循环停止并等待其停止。python2.6版本。 8 9 BaseServer.address_family: 地址家族,比如socket.AF_INET和socket.AF_UNIX。 10 11 BaseServer.RequestHandlerClass:用户提供的请求处理类,这个类为每个请求创建实例。 12 13 BaseServer.server_address:服务器侦听的地址。格式根据协议家族地址的各不相同,请参阅socket模块的文档。 14 15 BaseServer.socketSocket:服务器上侦听传入的请求socket对象的服务器。 16 17 服务器类支持下面的类变量: 18 19 BaseServer.allow_reuse_address:服务器是否允许地址的重用。默认为false ,并且可在子类中更改。 20 21 BaseServer.request_queue_size 22 23 请求队列的大小。如果单个请求需要很长的时间来处理,服务器忙时请求被放置到队列中,最多可以放request_queue_size个。一旦队列已满,来自客户端的请求将得到 “Connection denied”错误。默认值通常为5 ,但可以被子类覆盖。 24 25 BaseServer.socket_type:服务器使用的套接字类型; socket.SOCK_STREAM和socket.SOCK_DGRAM等。 26 27 BaseServer.timeout:超时时间,以秒为单位,或 None表示没有超时。如果handle_request()在timeout内没有收到请求,将调用handle_timeout()。 28 29 下面方法可以被子类重载,它们对服务器对象的外部用户没有影响。 30 31 BaseServer.finish_request():实际处理RequestHandlerClass发起的请求并调用其handle()方法。 常用。 32 33 BaseServer.get_request():接受socket请求,并返回二元组包含要用于与客户端通信的新socket对象,以及客户端的地址。 34 35 BaseServer.handle_error(request, client_address):如果RequestHandlerClass的handle()方法抛出异常时调用。默认操作是打印traceback到标准输出,并继续处理其他请求。 36 37 BaseServer.handle_timeout():超时处理。默认对于forking服务器是收集退出的子进程状态,threading服务器则什么都不做。 38 39 BaseServer.process_request(request, client_address) :调用finish_request()创建RequestHandlerClass的实例。如果需要,此功能可以创建新的进程或线程来处理请求,ForkingMixIn和ThreadingMixIn类做到这点。常用。 40 41 BaseServer.server_activate():通过服务器的构造函数来激活服务器。默认的行为只是监听服务器套接字。可重载。 42 43 BaseServer.server_bind():通过服务器的构造函数中调用绑定socket到所需的地址。可重载。 44 45 BaseServer.verify_request(request, client_address):返回一个布尔值,如果该值为True ,则该请求将被处理,反之请求将被拒绝。此功能可以重写来实现对服务器的访问控制。默认的实现始终返回True。client_address可以限定客户端,比如只处理指定ip区间的请求。 常用。
1 class BaseServer: 2 3 """Base class for server classes. 4 5 Methods for the caller: 6 7 - __init__(server_address, RequestHandlerClass) 8 - serve_forever(poll_interval=0.5) 9 - shutdown() 10 - handle_request() # if you do not use serve_forever() 11 - fileno() -> int # for selector 12 13 Methods that may be overridden: 14 15 - server_bind() 16 - server_activate() 17 - get_request() -> request, client_address 18 - handle_timeout() 19 - verify_request(request, client_address) 20 - server_close() 21 - process_request(request, client_address) 22 - shutdown_request(request) 23 - close_request(request) 24 - service_actions() 25 - handle_error() 26 27 Methods for derived classes: 28 29 - finish_request(request, client_address) 30 31 Class variables that may be overridden by derived classes or 32 instances: 33 34 - timeout 35 - address_family 36 - socket_type 37 - allow_reuse_address 38 39 Instance variables: 40 41 - RequestHandlerClass 42 - socket 43 44 """ 45 46 timeout = None 47 48 def __init__(self, server_address, RequestHandlerClass): 49 """Constructor. May be extended, do not override.""" 50 self.server_address = server_address 51 self.RequestHandlerClass = RequestHandlerClass 52 self.__is_shut_down = threading.Event() 53 self.__shutdown_request = False 54 55 def server_activate(self): 56 """Called by constructor to activate the server. 57 58 May be overridden. 59 60 """ 61 pass 62 63 def serve_forever(self, poll_interval=0.5): 64 """Handle one request at a time until shutdown. 65 66 Polls for shutdown every poll_interval seconds. Ignores 67 self.timeout. If you need to do periodic tasks, do them in 68 another thread. 69 """ 70 self.__is_shut_down.clear() 71 try: 72 # XXX: Consider using another file descriptor or connecting to the 73 # socket to wake this up instead of polling. Polling reduces our 74 # responsiveness to a shutdown request and wastes cpu at all other 75 # times. 76 with _ServerSelector() as selector: 77 selector.register(self, selectors.EVENT_READ) 78 79 while not self.__shutdown_request: 80 ready = selector.select(poll_interval) 81 if ready: 82 self._handle_request_noblock() 83 84 self.service_actions() 85 finally: 86 self.__shutdown_request = False 87 self.__is_shut_down.set() 88 89 def shutdown(self): 90 """Stops the serve_forever loop. 91 92 Blocks until the loop has finished. This must be called while 93 serve_forever() is running in another thread, or it will 94 deadlock. 95 """ 96 self.__shutdown_request = True 97 self.__is_shut_down.wait() 98 99 def service_actions(self): 100 """Called by the serve_forever() loop. 101 102 May be overridden by a subclass / Mixin to implement any code that 103 needs to be run during the loop. 104 """ 105 pass 106 107 # The distinction between handling, getting, processing and finishing a 108 # request is fairly arbitrary. Remember: 109 # 110 # - handle_request() is the top-level call. It calls selector.select(), 111 # get_request(), verify_request() and process_request() 112 # - get_request() is different for stream or datagram sockets 113 # - process_request() is the place that may fork a new process or create a 114 # new thread to finish the request 115 # - finish_request() instantiates the request handler class; this 116 # constructor will handle the request all by itself 117 118 def handle_request(self): 119 """Handle one request, possibly blocking. 120 121 Respects self.timeout. 122 """ 123 # Support people who used socket.settimeout() to escape 124 # handle_request before self.timeout was available. 125 timeout = self.socket.gettimeout() 126 if timeout is None: 127 timeout = self.timeout 128 elif self.timeout is not None: 129 timeout = min(timeout, self.timeout) 130 if timeout is not None: 131 deadline = time() + timeout 132 133 # Wait until a request arrives or the timeout expires - the loop is 134 # necessary to accommodate early wakeups due to EINTR. 135 with _ServerSelector() as selector: 136 selector.register(self, selectors.EVENT_READ) 137 138 while True: 139 ready = selector.select(timeout) 140 if ready: 141 return self._handle_request_noblock() 142 else: 143 if timeout is not None: 144 timeout = deadline - time() 145 if timeout < 0: 146 return self.handle_timeout() 147 148 def _handle_request_noblock(self): 149 """Handle one request, without blocking. 150 151 I assume that selector.select() has returned that the socket is 152 readable before this function was called, so there should be no risk of 153 blocking in get_request(). 154 """ 155 try: 156 request, client_address = self.get_request() 157 except OSError: 158 return 159 if self.verify_request(request, client_address): 160 try: 161 self.process_request(request, client_address) 162 except Exception: 163 self.handle_error(request, client_address) 164 self.shutdown_request(request) 165 except: 166 self.shutdown_request(request) 167 raise 168 else: 169 self.shutdown_request(request) 170 171 def handle_timeout(self): 172 """Called if no new request arrives within self.timeout. 173 174 Overridden by ForkingMixIn. 175 """ 176 pass 177 178 def verify_request(self, request, client_address): 179 """Verify the request. May be overridden. 180 181 Return True if we should proceed with this request. 182 183 """ 184 return True 185 186 def process_request(self, request, client_address): 187 """Call finish_request. 188 189 Overridden by ForkingMixIn and ThreadingMixIn. 190 191 """ 192 self.finish_request(request, client_address) 193 self.shutdown_request(request) 194 195 def server_close(self): 196 """Called to clean-up the server. 197 198 May be overridden. 199 200 """ 201 pass 202 203 def finish_request(self, request, client_address): 204 """Finish one request by instantiating RequestHandlerClass.""" 205 self.RequestHandlerClass(request, client_address, self) 206 207 def shutdown_request(self, request): 208 """Called to shutdown and close an individual request.""" 209 self.close_request(request) 210 211 def close_request(self, request): 212 """Called to clean up an individual request.""" 213 pass 214 215 def handle_error(self, request, client_address): 216 """Handle an error gracefully. May be overridden. 217 218 The default is to print a traceback and continue. 219 220 """ 221 print('-'*40, file=sys.stderr) 222 print('Exception happened during processing of request from', 223 client_address, file=sys.stderr) 224 import traceback 225 traceback.print_exc() 226 print('-'*40, file=sys.stderr) 227 228 def __enter__(self): 229 return self 230 231 def __exit__(self, *args): 232 self.server_close()
4.TCPServer方法
- server_bind
- server_activate
- server_close
- fileno
- get_request
- shutdown_request
- close_request
1 class TCPServer(BaseServer): 2 3 """Base class for various socket-based server classes. 4 5 Defaults to synchronous IP stream (i.e., TCP). 6 7 Methods for the caller: 8 9 - __init__(server_address, RequestHandlerClass, bind_and_activate=True) 10 - serve_forever(poll_interval=0.5) 11 - shutdown() 12 - handle_request() # if you don't use serve_forever() 13 - fileno() -> int # for selector 14 15 Methods that may be overridden: 16 17 - server_bind() 18 - server_activate() 19 - get_request() -> request, client_address 20 - handle_timeout() 21 - verify_request(request, client_address) 22 - process_request(request, client_address) 23 - shutdown_request(request) 24 - close_request(request) 25 - handle_error() 26 27 Methods for derived classes: 28 29 - finish_request(request, client_address) 30 31 Class variables that may be overridden by derived classes or 32 instances: 33 34 - timeout 35 - address_family 36 - socket_type 37 - request_queue_size (only for stream sockets) 38 - allow_reuse_address 39 40 Instance variables: 41 42 - server_address 43 - RequestHandlerClass 44 - socket 45 46 """ 47 48 address_family = socket.AF_INET 49 50 socket_type = socket.SOCK_STREAM 51 52 request_queue_size = 5 53 54 allow_reuse_address = False 55 56 def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): 57 """Constructor. May be extended, do not override.""" 58 BaseServer.__init__(self, server_address, RequestHandlerClass) 59 self.socket = socket.socket(self.address_family, 60 self.socket_type) 61 if bind_and_activate: 62 try: 63 self.server_bind() 64 self.server_activate() 65 except: 66 self.server_close() 67 raise 68 69 def server_bind(self): 70 """Called by constructor to bind the socket. 71 72 May be overridden. 73 74 """ 75 if self.allow_reuse_address: 76 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 77 self.socket.bind(self.server_address) 78 self.server_address = self.socket.getsockname() 79 80 def server_activate(self): 81 """Called by constructor to activate the server. 82 83 May be overridden. 84 85 """ 86 self.socket.listen(self.request_queue_size) 87 88 def server_close(self): 89 """Called to clean-up the server. 90 91 May be overridden. 92 93 """ 94 self.socket.close() 95 96 def fileno(self): 97 """Return socket file number. 98 99 Interface required by selector. 100 101 """ 102 return self.socket.fileno() 103 104 def get_request(self): 105 """Get the request and client address from the socket. 106 107 May be overridden. 108 109 """ 110 return self.socket.accept() 111 112 def shutdown_request(self, request): 113 """Called to shutdown and close an individual request.""" 114 try: 115 #explicitly shutdown. socket.close() merely releases 116 #the socket and waits for GC to perform the actual close. 117 request.shutdown(socket.SHUT_WR) 118 except OSError: 119 pass #some platforms may raise ENOTCONN here 120 self.close_request(request) 121 122 def close_request(self, request): 123 """Called to clean up an individual request.""" 124 request.close()
5.UDPServer方法
- get_request
- server_activate
- shutdown_request
- close_request
1 class UDPServer(TCPServer): 2 3 """UDP server class.""" 4 5 allow_reuse_address = False 6 7 socket_type = socket.SOCK_DGRAM 8 9 max_packet_size = 8192 10 11 def get_request(self): 12 data, client_addr = self.socket.recvfrom(self.max_packet_size) 13 return (data, self.socket), client_addr 14 15 def server_activate(self): 16 # No need to call listen() for UDP. 17 pass 18 19 def shutdown_request(self, request): 20 # No need to shutdown anything. 21 self.close_request(request) 22 23 def close_request(self, request): 24 # No need to close anything. 25 pass
三、request类(request handle class)
1.request类
- class BaseRequestHandler
- class StreamRequestHandler(BaseRequestHandler)
- class DatagramRequestHandler(BaseRequestHandler)
BaseRequestHandle类的实例化可以实现以下方法:
-
sock.handle()调用该方法执行实际的请求操作.调用函数可以不带任何参数,但是几个实例变量包含有用的值.sock.request包含请求,sock.client_address包含客户端的地址,sock.server包含调用处理程序的实例.对于TCP之类的数据流服务,sock.request属性是套接字对象.
- 对于数据报服务,还是包含收到数据的字节字符串.
-
sock.setup()该方法在handle()之前调用.默认情况下,不执行任何操作.如果希望服务器实现更多连接设置(如建立SSL连接),则无需调用该方法.
-
sock.finish()调用本方法可以在执行完handle()之后执行清除操作.默认情况下,不执行任何操作.如果setup()和handle()方法都不生成异常,则无需调用该方法.
- 如果知道应用程序只能操纵面向数据流的连接(如TCP),那么应从StreamRequestHandle继承,而不是BaseRequestHandler.StreaRequestHandler类设置了两个属性,sock.wfile是将数据写入客户端的类文件对象,sock.rfile是从客户端读取数据的类文件对象.
- 如果编写针对数据包操作的处理程序并将响应持续返回给发送方,那么它应当从DategramRequestHandler继承.它提供的类接口与StreamREquestHandler相同.
2.继承图
3.源码
1 class BaseRequestHandler: 2 3 """Base class for request handler classes. 4 5 This class is instantiated for each request to be handled. The 6 constructor sets the instance variables request, client_address 7 and server, and then calls the handle() method. To implement a 8 specific service, all you need to do is to derive a class which 9 defines a handle() method. 10 11 The handle() method can find the request as self.request, the 12 client address as self.client_address, and the server (in case it 13 needs access to per-server information) as self.server. Since a 14 separate instance is created for each request, the handle() method 15 can define other arbitrary instance variables. 16 17 """ 18 19 def __init__(self, request, client_address, server): 20 self.request = request 21 self.client_address = client_address 22 self.server = server 23 self.setup() 24 try: 25 self.handle() 26 finally: 27 self.finish() 28 29 def setup(self): 30 pass 31 32 def handle(self): 33 pass 34 35 def finish(self): 36 pass 37 38 39 # The following two classes make it possible to use the same service 40 # class for stream or datagram servers. 41 # Each class sets up these instance variables: 42 # - rfile: a file object from which receives the request is read 43 # - wfile: a file object to which the reply is written 44 # When the handle() method returns, wfile is flushed properly
1 class StreamRequestHandler(BaseRequestHandler): 2 3 """Define self.rfile and self.wfile for stream sockets.""" 4 5 # Default buffer sizes for rfile, wfile. 6 # We default rfile to buffered because otherwise it could be 7 # really slow for large data (a getc() call per byte); we make 8 # wfile unbuffered because (a) often after a write() we want to 9 # read and we need to flush the line; (b) big writes to unbuffered 10 # files are typically optimized by stdio even when big reads 11 # aren't. 12 rbufsize = -1 13 wbufsize = 0 14 15 # A timeout to apply to the request socket, if not None. 16 timeout = None 17 18 # Disable nagle algorithm for this socket, if True. 19 # Use only when wbufsize != 0, to avoid small packets. 20 disable_nagle_algorithm = False 21 22 def setup(self): 23 self.connection = self.request 24 if self.timeout is not None: 25 self.connection.settimeout(self.timeout) 26 if self.disable_nagle_algorithm: 27 self.connection.setsockopt(socket.IPPROTO_TCP, 28 socket.TCP_NODELAY, True) 29 self.rfile = self.connection.makefile('rb', self.rbufsize) 30 if self.wbufsize == 0: 31 self.wfile = _SocketWriter(self.connection) 32 else: 33 self.wfile = self.connection.makefile('wb', self.wbufsize) 34 35 def finish(self): 36 if not self.wfile.closed: 37 try: 38 self.wfile.flush() 39 except socket.error: 40 # A final socket error may have occurred here, such as 41 # the local error ECONNABORTED. 42 pass 43 self.wfile.close() 44 self.rfile.close()
1 class DatagramRequestHandler(BaseRequestHandler): 2 3 """Define self.rfile and self.wfile for datagram sockets.""" 4 5 def setup(self): 6 from io import BytesIO 7 self.packet, self.socket = self.request 8 self.rfile = BytesIO(self.packet) 9 self.wfile = BytesIO() 10 11 def finish(self): 12 self.socket.sendto(self.wfile.getvalue(), self.client_address)
四、线程与进程类
- ForkingMinIn 实现了核心的进程化功能,用于与服务器类进行混合(min-in),以提供一些异步特性.不要直接生成这个类的对象
- ThreadingMinIn 实现了核心的线程化功能,用于与服务器类进行混合(min-in),以提供一些异步特性,不要直接生成这个类的对象
- ForkingTCPServer ForkingMinIn与TCPServer的组合
- ForkingUDPServer ForkingMinIn与UDPServer的组合
五、server类和request类关系与继承
说明:
六、TCPServer 实例
1.创建一个server需要的几个步骤:
原文:
- First, you must create a request handler class by subclassing the BaseRequestHandlerclass and overriding its handle() method; this method will process incoming requests.
- Second, you must instantiate one of the server classes, passing it the server’s address and the request handler class.
- Then call the handle_request() or serve_forever() method of the server object to process one or many requests.
- Finally, call server_close() to close the socket.
翻译:
- 首先,您必须创建一个请求处理类的子类 继承BaseRequestHandlerclass,并重写父类里的handle()方法,该方法将处理传入的请求。
- 其次,你必须实例化一个服务器的类,并且传递服务器的地址,端口和上面一步创建的类名。
- 然后调用handle_request()或者serve_forever()方法来处理一个或多个请求。handle_request()只处理一个请求,serve_forever()处理多个请求,永远执行。
- 最后,调用server_close()关闭套接字。
2.实例1
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): #服务类,监听绑定等等 """ The request handler class for our server. It is instantiated once per connection to the server, and must override the handle() method to implement communication to the client. """ def handle(self): #请求处理类,所有请求的交互都是在handle里执行的 # self.request is the TCP socket connected to the client self.data = self.request.recv(1024).strip()#每一个请求都会实例化MyTCPHandler(socketserver.BaseRequestHandler): print("{} wrote:".format(self.client_address[0])) print(self.data) # just send back the same data, but upper-cased self.request.sendall(self.data.upper())#sendall是重复调用send. if __name__ == "__main__": HOST, PORT = "localhost", 9999 # Create the server, binding to localhost on port 9999 server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) # Activate the server; this will keep running until you # interrupt the program with Ctrl-C server.serve_forever() server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) #线程 # server = socketserver.ForkingTCPServer((HOST, PORT), MyTCPHandler) #多进程 linux适用 # server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) 单进程
3.实例2
Server端:
import socketserver class Myserver(socketserver.BaseRequestHandler): def handle(self): #self.request 就相当于一个 conn print(self.request.recv(1024).decode('utf-8')) if __name__ == '__main__': server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),Myserver) server.serve_forever()
Client端:
import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) sk.send('人生苦短,请用Python!'.encode('utf-8')) sk.close()
执行结果:
人生苦短,请用Python!
查找属性的顺序:ThreadingTCPServer->ThreadingMixIn->TCPServer->BaseServer
- 实例化得到ftpserver,先找类ThreadingTCPServer的__init__,在TCPServer中找到,进而执行server_bind,server_active
- 找ftpserver下的serve_forever,在BaseServer中找到,进而执行self._handle_request_noblock(),该方法同样是在BaseServer中
- 执行self._handle_request_noblock()进而执行request, client_address = self.get_request()(就是TCPServer中的self.socket.accept()),然后执行self.process_request(request, client_address)
- 在ThreadingMixIn中找到process_request,开启多线程应对并发,进而执行process_request_thread,执行self.finish_request(request, client_address)
- 上述四部分完成了链接循环,本部分开始进入处理通讯部分,在BaseServer中找到finish_request,触发我们自己定义的类的实例化,去找__init__方法,而我们自己定义的类没有该方法,则去它的父类也就是BaseRequestHandler中
七、UDPServer 实例
server:
import socketserver class MyUDPHandler(socketserver.BaseRequestHandler): """ This class works similar to the TCP handler class, except that self.request consists of a pair of data and client socket, and since there is no connection the client address must be given explicitly when sending data back via sendto(). """ def handle(self): data = self.request[0].strip() socket = self.request[1] print("{} wrote:".format(self.client_address[0])) print(data) socket.sendto(data.upper(), self.client_address) if __name__ == "__main__": HOST, PORT = "localhost", 9999 with socketserver.UDPServer((HOST, PORT), MyUDPHandler) as server: server.serve_forever()
client:
import socket import sys HOST, PORT = "localhost", 9999 data = " ".join(sys.argv[1:]) # SOCK_DGRAM is the socket type to use for UDP sockets sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # As you can see, there is no connect() call; UDP has no connections. # Instead, data is directly sent to the recipient via sendto(). sock.sendto(bytes(data + " ", "utf-8"), (HOST, PORT)) received = str(sock.recv(1024), "utf-8") print("Sent: {}".format(data)) print("Received: {}".format(received))