def clear_buffer(self, remove_total_filter=False): # there is a window of time after the socket has been created and # before bind/attaching a filter where packets can be queued onto the # socket buffer # see comments in function set_kernel_filter() in libpcap's # pcap-linux.c. libpcap sets a total filter which does not match any # packet. It then clears what is already in the socket # before setting the desired filter total_fstring, prog = compile_bpf(total_filter) socket.setsockopt(self, SOL_SOCKET, SO_ATTACH_FILTER, total_fstring) self.setblocking(0) while True: try: self.recvfrom(0) except error as e: if e.args[0] == errno.ENETDOWN: # we only get this exception once per down event # there may be more packets left to clean pass elif e.args[0] in [errno.EAGAIN, errno.EWOULDBLOCK]: break else: raise self.setblocking(1) if remove_total_filter: # total_fstring ignored socket.setsockopt(self, SOL_SOCKET, SO_DETACH_FILTER, total_fstring)
def __init__(self, ifname, bpf=None): self.ifname = ifname # lookup the interface details with IPRoute() as ip: for link in ip.get_links(): if link.get_attr('IFLA_IFNAME') == ifname: break else: raise IOError(2, 'Link not found') self.l2addr = link.get_attr('IFLA_ADDRESS') self.ifindex = link['index'] # bring up the socket socket.__init__(self, AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) socket.bind(self, (self.ifname, ETH_P_ALL)) if bpf: fstring, self.fprog = compile_bpf(bpf) socket.setsockopt(self, SOL_SOCKET, SO_ATTACH_FILTER, fstring)
def __init__(self, ifname, bpf=None): self.ifname = ifname # lookup the interface details with IPRoute() as ip: for link in ip.get_links(): if link.get_attr("IFLA_IFNAME") == ifname: break else: raise IOError(2, "Link not found") self.l2addr = link.get_attr("IFLA_ADDRESS") self.ifindex = link["index"] # bring up the socket socket.__init__(self, AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) socket.bind(self, (self.ifname, ETH_P_ALL)) if bpf: fstring, self.fprog = compile_bpf(bpf) socket.setsockopt(self, SOL_SOCKET, SO_ATTACH_FILTER, fstring)
def __init__(self, ifname, bpf=None): self.ifname = ifname # lookup the interface details with IPRoute() as ip: for link in ip.get_links(): if link.get_attr('IFLA_IFNAME') == ifname: break else: raise IOError(2, 'Link not found') self.l2addr = link.get_attr('IFLA_ADDRESS') self.ifindex = link['index'] # bring up the socket socket.__init__(self, AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) socket.bind(self, (self.ifname, ETH_P_ALL)) if bpf: self.clear_buffer() fstring, self.fprog = compile_bpf(bpf) socket.setsockopt(self, SOL_SOCKET, SO_ATTACH_FILTER, fstring) else: self.clear_buffer(remove_total_filter=True)
def clear_buffer(self, remove_total_filter=False): # there is a window of time after the socket has been created and # before bind/attaching a filter where packets can be queued onto the # socket buffer # see comments in function set_kernel_filter() in libpcap's # pcap-linux.c. libpcap sets a total filter which does not match any # packet. It then clears what is already in the socket # before setting the desired filter total_fstring, prog = compile_bpf(total_filter) socket.setsockopt(self, SOL_SOCKET, SO_ATTACH_FILTER, total_fstring) self.setblocking(0) while True: try: self.recvfrom(0) except error as e: # Resource temporarily unavailable if e.args[0] != 11: raise break self.setblocking(1) if remove_total_filter: # total_fstring ignored socket.setsockopt(self, SOL_SOCKET, SO_DETACH_FILTER, total_fstring)
def connect(self, address): socket.connect(self, address) socket.setsockopt(self, IPPROTO_TCP, TCP_NODELAY, 1) raw_send = self.send def send_x(data, timeout=0): view = memoryview(data) size = len(view) offset = 0 while offset < size: _, ready_to_write, _ = select((), (self, ), (), timeout) while not ready_to_write: _, ready_to_write, _ = select((), (self, ), (), timeout) sent = raw_send(view[offset:]) if sent == 0: raise SocketError("Peer closed connection") offset += sent raw_recv = self.recv received = [ b"" ] # the functions below assume exactly one item in this list on entry and exit def recv_headers(timeout=0): end = received[0].find(b"\r\n\r\n") while end == -1: ready_to_read, _, _ = select((self, ), (), (), timeout) while not ready_to_read: ready_to_read, _, _ = select((self, ), (), (), timeout) data = raw_recv(8192) received[0] += data end = received[0].find(b"\r\n\r\n") if data == b"" and end == -1: raise SocketError("Peer closed connection") data, received[0] = received[0][:end], received[0][(end + 4):] return data.split(b"\r\n") def recv_content(length=None, timeout=0): if length is None: # receive until closed if received[0]: yield received[0] received[0] = b"" more = True while more: ready_to_read, _, _ = select((self, ), (), (), timeout) while not ready_to_read: ready_to_read, _, _ = select((self, ), (), (), timeout) data = raw_recv(8192) if data == b"": more = False else: yield data else: assert length >= 0 # receive fixed amount while length != 0: data, received[0] = received[0][:length], received[0][ length:] size = len(data) if size != 0: yield data length -= size if length != 0: ready_to_read, _, _ = select((self, ), (), (), timeout) while not ready_to_read: ready_to_read, _, _ = select((self, ), (), (), timeout) data = raw_recv(8192) if data == b"": raise SocketError("Peer closed connection") received[0] += data def recv_line(timeout=0): end = received[0].find(b"\r\n") while end == -1: ready_to_read, _, _ = select((self, ), (), (), timeout) while not ready_to_read: ready_to_read, _, _ = select((self, ), (), (), timeout) data = raw_recv(8192) received[0] += data end = received[0].find(b"\r\n") if data == b"" and end == -1: raise SocketError("Peer closed connection") data, received[0] = received[0][:end], received[0][(end + 2):] return data def recv_exact(length, timeout=0): available = len(received[0]) while available < length: ready_to_read, _, _ = select((self, ), (), (), timeout) while not ready_to_read: ready_to_read, _, _ = select((self, ), (), (), timeout) data = raw_recv(8192) received[0] += data available += len(data) if data == b"" and available < length: raise SocketError("Peer closed connection") data, received[0] = received[0][:length], received[0][length:] return data def recv_chunked_content(timeout=0): chunk_size = -1 while chunk_size != 0: chunk_size = int(recv_line(timeout=timeout), 16) if chunk_size != 0: yield recv_exact(chunk_size, timeout=timeout) recv_exact(2, timeout=timeout) self.send_x = send_x self.recv_headers = recv_headers self.recv_content = recv_content self.recv_chunked_content = recv_chunked_content
from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR import pickle from time import sleep socket = socket(AF_INET, SOCK_STREAM) socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) socket.bind(("", 2001)) socket.listen(2) print("Server running...") player1, player1_addr = socket.accept() # accept player1 print(f"{player1_addr[0]} has been connected") player2, player2_addr = socket.accept() # accept player2 print(f"{player2_addr[0]} has been connected") player1_win = False player2_win = False player1_shot = 0 player2_shot = 0 player1_coordinates = pickle.loads(player1.recv(1024)) # recv player1 ship coordinates player2_coordinates = pickle.loads(player2.recv(1024)) # recv player2 ship coordinates while True: # send ready to player1 if player2_win: player1.send(pickle.dumps(["You lose", player1_shot, player2_shot])) player2.send(pickle.dumps(["You win", player1_shot, player2_shot])) else:
def bind_socket(self, socket: socket) -> None: socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) socket.bind(('0.0.0.0', 14143)) socket.listen(10) # 10 clients max print(colored(f'Serving at http://localhost:14143', 'green'))
def connect(self, address): socket.connect(self, address) socket.setsockopt(self, IPPROTO_TCP, TCP_NODELAY, 1) raw_send = self.send def send_x(data, timeout=0): view = memoryview(data) size = len(view) offset = 0 while offset < size: _, ready_to_write, _ = select((), (self,), (), timeout) while not ready_to_write: _, ready_to_write, _ = select((), (self,), (), timeout) sent = raw_send(view[offset:]) if sent == 0: raise SocketError("Peer closed connection") offset += sent raw_recv = self.recv received = [b""] # the functions below assume exactly one item in this list on entry and exit def recv_headers(timeout=0): end = received[0].find(b"\r\n\r\n") while end == -1: ready_to_read, _, _ = select((self,), (), (), timeout) while not ready_to_read: ready_to_read, _, _ = select((self,), (), (), timeout) data = raw_recv(8192) received[0] += data end = received[0].find(b"\r\n\r\n") if data == b"" and end == -1: raise SocketError("Peer closed connection") data, received[0] = received[0][:end], received[0][(end + 4):] return data.split(b"\r\n") def recv_content(length=None, timeout=0): if length is None: # receive until closed if received[0]: yield received[0] received[0] = b"" more = True while more: ready_to_read, _, _ = select((self,), (), (), timeout) while not ready_to_read: ready_to_read, _, _ = select((self,), (), (), timeout) data = raw_recv(8192) if data == b"": more = False else: yield data else: assert length >= 0 # receive fixed amount while length != 0: data, received[0] = received[0][:length], received[0][length:] size = len(data) if size != 0: yield data length -= size if length != 0: ready_to_read, _, _ = select((self,), (), (), timeout) while not ready_to_read: ready_to_read, _, _ = select((self,), (), (), timeout) data = raw_recv(8192) if data == b"": raise SocketError("Peer closed connection") received[0] += data def recv_line(timeout=0): end = received[0].find(b"\r\n") while end == -1: ready_to_read, _, _ = select((self,), (), (), timeout) while not ready_to_read: ready_to_read, _, _ = select((self,), (), (), timeout) data = raw_recv(8192) received[0] += data end = received[0].find(b"\r\n") if data == b"" and end == -1: raise SocketError("Peer closed connection") data, received[0] = received[0][:end], received[0][(end + 2):] return data def recv_exact(length, timeout=0): available = len(received[0]) while available < length: ready_to_read, _, _ = select((self,), (), (), timeout) while not ready_to_read: ready_to_read, _, _ = select((self,), (), (), timeout) data = raw_recv(8192) received[0] += data available += len(data) if data == b"" and available < length: raise SocketError("Peer closed connection") data, received[0] = received[0][:length], received[0][length:] return data def recv_chunked_content(timeout=0): chunk_size = -1 while chunk_size != 0: chunk_size = int(recv_line(timeout=timeout), 16) if chunk_size != 0: yield recv_exact(chunk_size, timeout=timeout) recv_exact(2, timeout=timeout) self.send_x = send_x self.recv_headers = recv_headers self.recv_content = recv_content self.recv_chunked_content = recv_chunked_content