Язык программирования Python
Шрифт:
PORT = 33333
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.bind((HOST, PORT))
while 1:
print «Слушаю порт 33333»
srv.listen(1)
sock, addr = srv.accept
while 1:
pal = sock.recv(1024)
if not pal:
break
print «Получено от %s:%s:" % addr, pal
lap = do_something(pal)
print «Отправлено %s:%s:" % addr, lap
sock.send(lap)
sock.close
Клиент:
Листинг
import socket
HOST = "" # удаленный
PORT = 33333 # порт на удаленном компьютере
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
sock.send(«ПАЛИНДРОМ»)
result = sock.recv(1024)
sock.close
print «Получено:", result
Примечание:
В примере использованы русские буквы: необходимо указывать кодировку.
Прежде всего, нужно запустить сервер. Сервер открывает сокет на локальной машине на порту 33333, и адресе 127.0.0.1. После этого он слушает (listen) порт. Когда на порту появляются данные, принимается (accept) входящее соединение. Метод accept возвращает пару — Socket–объект и адрес удаленного компьютера, устанавливающего соединение (пара — IP–адрес, порт на удаленной машине). После этого можно применять методы recv и send для общения с клиентом. В recv задается число байтов в очередной порции. От клиента может прийти и меньшее количество данных.
Код программы–клиента достаточно очевиден. Метод connect устанавливает соединение с удаленным хостом (в приведенном примере он расположен на той же машине). Данные передаются методом send и принимаются методом recv — аналогично тому, что происходит на сервере.
Модуль socket имеет несколько вспомогательных функций. В частности, функции для работы с системой доменных имен (DNS):
Листинг
>>> import socket
>>> socket.gethostbyaddr('www.onego.ru')
('www.onego.ru', [], ['195.161.136.4'])
>>> socket.gethostbyaddr('195.161.136.4')
('www.onego.ru', [], ['195.161.136.4'])
>>> socket.gethostname
'rnd.onego.ru'
В новых версиях Python появилась такая функция как socket.getservbyname. Она позволяет преобразовывать наименования Интернет–сервисов в общепринятые номера портов:
Листинг
>>> for srv in 'http', 'ftp', 'imap', 'pop3', 'smtp':
… print socket.getservbyname(srv, 'tcp'), srv
…
80 http
21 ftp
143 imap
110 pop3
25 smtp
Модуль также содержит большое количество констант для указания протоколов, типов сокетов, коммуникационных доменов и т.п. Другие функции модуля socket можно при необходимости изучить по документации.
Модуль smtplib
Сообщения электронной почты в Интернете передаются от клиента к серверу и между серверами в основном по протоколу SMTP (Simple Mail Transfer Protocol, простой протокол передачи почты). Протокол SMTP и ESMTP (расширенный вариант SMTP) описаны в RFC 821 и RFC 1869. Для работы с SMTP в стандартной библиотеке
Листинг
smtplib.SMTP([host[, port]])
Параметры host и port задают адрес и порт SMTP–сервера, через который будет отправляться почта. По умолчанию, port=25. Если host задан, конструктор сам установит соединение, иначе придется отдельно вызывать метод connect. Экземпляры класса SMTP имеют методы для всех распространенных команд SMTP–протокола, но для отправки почты достаточно вызова конструктора и методов sendmail и quit:
Листинг
# -*- coding: cp1251 -*-from smtplib import SMTP
fromaddr = «[email protected]» # От кого
toaddr = «[email protected]» # Кому
message = ""«From: Student <%(fromaddr)s>
To: Lecturer <%(toaddr)s>
Subject: From Python course student
MIME–Version: 1.0
Content–Type: text/plain; charset=Windows–1251
Content–Transfer–Encoding: 8bit
Здравствуйте! Я изучаю курс по языку Python и
отправляю письмо его автору.
"""
connect = SMTP('mail.onego.ru')
connect.set_debuglevel(1)
connect.sendmail(fromaddr, toaddr, message % vars)
connect.quit
Следует заметить, что toaddr в сообщении (в поле To) и при отправке могут не совпадать. Дело в том, что получатель и отправитель в ходе SMTP–сессии передается командами SMTP–протокола. При запуске указанного выше примера на экране появится отладочная информация (ведь уровень отладки задан равным 1):
Листинг
send: 'ehlo rnd.onego.ru\r\n'
reply: '250–mail.onego.ru Hello as3–042.dialup.onego.ru [195.161.147.4], pleased to meet you\r\n'
send: 'mail FROM:<[email protected]> size=270\r\n'
reply: '250 2.1.0 <[email protected]>… Sender ok\r\n'
send: 'rcpt TO:<[email protected]>\r\n'
reply: '250 2.1.5 <[email protected]>… Recipient ok\r\n'
send: 'data\r\n'
reply: '354 Enter mail, end with ".» on a line by itself\r\n'
send: 'From: Student <[email protected]>\r\n … '
reply: '250 2.0.0 iBPFgQ7q028433 Message accepted for delivery\r\n'
send: 'quit\r\n'
reply: '221 2.0.0 mail.onego.ru closing connection\r\n'
Из этой (несколько сокращенной) отладочной информации можно увидеть, что клиент отправляет (send) команды SMTP–серверу (EHLO, MAIL FROM, RCPT TO, DATA, QUIT), а тот выполняет команды и отвечает (reply), возвращая код возврата.
В ходе одной SMTP–сессии можно отправить сразу несколько писем подряд, если не вызывать quit.
В принципе, команды SMTP можно подавать и отдельно: для этого у объекта–соединения есть методы (helo, ehlo, expn, help, mail, rcpt, vrfy, send, noop, data), соответствующие одноименным командам SMTP–протокола.