Сокеты

Введение

Примеры

  • 0

    Отправка данных через UDP

    UDP - это протокол без установления соединения. Сообщения другим процессам или компьютерам отправляются без установления какого-либо соединения. Там нет автоматического подтверждения, если ваше сообщение было получено. UDP обычно используется в приложениях, чувствительных к задержке, или в приложениях, отправляющих широковещательные сообщения в сети.

    Следующий код отправляет сообщение процессу, прослушивающему порт localhost 6667 с использованием UDP

    Обратите внимание , что нет никакой необходимости «закрыть» сокет после отправки, поскольку UDP является установление соединения .

     from socket import socket, AF_INET, SOCK_DGRAM
    s = socket(AF_INET, SOCK_DGRAM)
    msg = ("Hello you there!").encode('utf-8')  # socket.sendto() takes bytes as input, hence we must encode the string first.
    s.sendto(msg, ('localhost', 6667)) 
    
    
     
  • 0

    Получение данных через UDP

    UDP - это протокол без установления соединения. Это означает, что одноранговые отправляющие сообщения не требуют установления соединения перед отправкой сообщений. socket.recvfrom , таким образом , возвращает кортеж ( msg [сообщение сокет получил], addr [адрес отправителя])

    UDP - сервер , использующий исключительно socket модуль:

     from socket import socket, AF_INET, SOCK_DGRAM
    sock = socket(AF_INET, SOCK_DGRAM)
    sock.bind(('localhost', 6667))
    
    while True:
        msg, addr = sock.recvfrom(8192)  # This is the amount of bytes to read at maximum
        print("Got message from %s: %s" % (addr, msg))
    
    
     

    Ниже приводится альтернативная реализация с использованием socketserver.UDPServer :

     from socketserver import BaseRequestHandler, UDPServer
    
    class MyHandler(BaseRequestHandler):
        def handle(self):
            print("Got connection from: %s" % self.client_address)
            msg, sock = self.request
            print("It said: %s" % msg)
            sock.sendto("Got your message!".encode(), self.client_address) # Send reply
    
    serv = UDPServer(('localhost', 6667), MyHandler)
    serv.serve_forever()
    
    
     

    По умолчанию sockets блока. Это означает, что выполнение скрипта будет ожидать, пока сокет не получит данные.

  • 0

    Отправка данных через TCP

    Отправка данных через Интернет возможна с помощью нескольких модулей. Модуль сокетов обеспечивает низкоуровневый доступ к операциям базовой операционной системы, отвечающим за отправку или получение данных с других компьютеров или процессов.

    Следующий код посылает строку байт b'Hello' на сервер TCP на порту 6667 на хосте локального хоста и закрывает соединение после завершения:

     from socket import socket, AF_INET, SOCK_STREAM
    s = socket(AF_INET, SOCK_STREAM)
    s.connect(('localhost', 6667))  # The address of the TCP server listening
    s.send(b'Hello')
    s.close()
    
     

    По умолчанию вывод сокетов блокируется, это означает, что программа будет ожидать подключения и отправлять вызовы, пока действие не будет «завершено». Для подключения это означает, что сервер фактически принимает соединение. Для отправки это означает только то, что в операционной системе достаточно буферного пространства, чтобы поставить в очередь данные для последующей отправки.

    Розетки всегда должны быть закрыты после использования.

  • 0

    Многопоточный сокет-сервер TCP

    При запуске без аргументов, эта программа запускается сервер сокета TCP , который прослушивает для подключения к 127.0.0.1 на порт 5000 . Сервер обрабатывает каждое соединение в отдельном потоке.

    При запуске с -c аргументом, эта программа подключается к серверу, считывает список клиентов, и выводит его. Список клиентов передается в виде строки JSON. Имя клиента может быть определен путем пропускания -n аргумент. Передавая разные имена, можно наблюдать влияние на список клиентов.

    client_list.py

    import argparse
    import json
    import socket
    import threading
    
    def handle_client(client_list, conn, address):
        name = conn.recv(1024)
        entry = dict(zip(['name', 'address', 'port'], [name, address[0], address[1]]))
        client_list[name] = entry
        conn.sendall(json.dumps(client_list))
        conn.shutdown(socket.SHUT_RDWR)
        conn.close()
    
    def server(client_list):
        print "Starting server..."
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('127.0.0.1', 5000))
        s.listen(5)
        while True:
            (conn, address) = s.accept()
            t = threading.Thread(target=handle_client, args=(client_list, conn, address))
            t.daemon = True
            t.start()
    
    def client(name):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(('127.0.0.1', 5000))
        s.send(name)
        data = s.recv(1024)
        result = json.loads(data)
        print json.dumps(result, indent=4)
    
    def parse_arguments():
        parser = argparse.ArgumentParser()
        parser.add_argument('-c', dest='client', action='store_true')
        parser.add_argument('-n', dest='name', type=str, default='name')
        result = parser.parse_args()
        return result
    
    def main():
        client_list = dict()
        args = parse_arguments()
        if args.client:
            client(args.name)
        else:
            try:
                server(client_list)
            except KeyboardInterrupt:
                print "Keyboard interrupt"
    
    if __name__ == '__main__':
        main()
    
     

    Выход сервера

     $ python client_list.py
    Starting server...
    
     

    Выход клиента

     $ python client_list.py -c -n name1
    {
        "name1": {
            "address": "127.0.0.1", 
            "port": 62210, 
            "name": "name1"
        }
    }
    
     

    Приемные буферы ограничены 1024 байтами. Если строковое представление JSON списка клиентов превышает этот размер, оно будет усечено. Это приведет к возникновению следующего исключения:

     ValueError: Unterminated string starting at: line 1 column 1023 (char 1022) 
  • 0

    Сырые сокеты в Linux

    Сначала вы отключите автоматическую контрольную сумму вашей сетевой карты:

     sudo ethtool -K eth1 tx off
     

    Затем отправьте свой пакет, используя сокет SOCK_RAW: `` `

    ! / usr / bin / env python

    из сокета импорта сокета, AF_PACKET, SOCK_RAW s = сокет (AF_PACKET, SOCK_RAW) s.bind (("eth1", 0))

    Мы собираем кадр Ethernet,

    но вы могли бы иметь все, что вы хотите вместо

    Посмотрите на модуль "struct" для более

    гибкая упаковка / распаковка двоичных данных

    и «binascii» для 32-битной CRC

    src_addr = "\ x01 \ x02 \ x03 \ x04 \ x05 \ x06" dst_addr = "\ x01 \ x02 \ x03 \ x04 \ x05 \ x06" полезная нагрузка = ( "[" 30) + "ПОЛЕЗНОЙ" + ( "]" 30 ) контрольная сумма = "\ x1a \ x2b \ x3c \ x4d" ethertype = "\ x08 \ x01"

    s.send (dst_addr + src_addr + Ethertype + полезная нагрузка + контрольная сумма)

Синтаксис

Параметры

Примечания