Документация по Python

Сокеты

В: Документация по Python

Отправка данных через 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)) 


 

Получение данных через 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 блока. Это означает, что выполнение скрипта будет ожидать, пока сокет не получит данные.

Отправка данных через 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()

 

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

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

Многопоточный сокет-сервер 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) 

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

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

 sudo ethtool -K eth1 tx off
 

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

Еще от кодкамп
Замечательно! Вы успешно подписались.
Добро пожаловать обратно! Вы успешно вошли
Вы успешно подписались на кодкамп.
Срок действия вашей ссылки истек.
Ура! Проверьте свою электронную почту на наличие волшебной ссылки для входа.
Успех! Ваша платежная информация обновлена.
Ваша платежная информация не была обновлена.