Python: сокеты не работают по локальной сети
Недавно я вернулся из отпуска, и мой базовый сервер сокетов python 2 теперь не может общаться с клиентами по локальной сети. Сервер находится на mac, а клиент – мой малиновый pi или мой Windows 7. Я упростил здесь код сервера и клиента, чтобы привести пример:
import socket from thread import * HOST = socket.gethostname() print HOST PORT = input ("Enter the PORT number (1 - 10,000)") s = socket.socket(socket.AF_INET, socket.SOCK_STREAM ) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) print "Socket Created" s.bind((HOST, PORT)) print "Socket Bind Complete" s.listen(10) print "Socket now listening" #Sending message to connected client #This only takes strings (words while True: #Wait to accept a connection - blocking call connection, addr = s.accept() print "Connection Established!" connection.send("Welcome to the server. Type something and hit enter\n") #loop so that function does not terminate and the thread does not end while True: #Receiving from client data = connection.recv(1024) if not data: break connection.sendall(data) print data connection.close() s.close()
import socket #for sockets s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print "Socket Created" #Get host and port info to connect host = raw_input("HOST >>> ") port = 2468 s.connect((host, port)) while True: #Send some data to the remote server message = raw_input(">>> ") #set the whole string s.sendall(message) reply = s.recv(1024) print reply
Что здесь происходит? Я получаю локальный IP-адрес, но сценарии по-прежнему не могут общаться. Это может быть проблема с ОС?
БОЛЬШЕ ИНФОРМАЦИИ
- Pinging а. Я смог выполнить ping PI с моего терминала Mac:
PING raspberrypi (67.63.55.3): 56 data bytes 64 bytes from 67.63.55.3: icmp_seq=0 ttl=240 time=17.434 ms 64 bytes from 67.63.55.3: icmp_seq=1 ttl=240 time=18.180 ms 64 bytes from 67.63.55.3: icmp_seq=2 ttl=240 time=22.046 ms 64 bytes from 67.63.55.3: icmp_seq=3 ttl=240 time=25.124 ms 64 bytes from 67.63.55.3: icmp_seq=4 ttl=240 time=31.773 ms
Мой Mac Firewall отключен. Я проверил [Raspberry Pi Stackexchange Site], чтобы узнать, имеет ли PI брандмауэр.
Я добавлю дополнительную информацию, как только проверю машину для Windows
Запуская оба сценария локально, им удается подключаться и общаться на моей машине. Вы столкнулись с сетевой проблемой, которую нужно легко отлаживать.
- Неверная привязка. На сервере распечатайте HOST, который вы получите. Если на сервере имеется более одного IP-адреса, вы можете попытаться связать его с неправильным. Вы также можете изменить его на “0.0.0.0” (только на стороне сервера) и посмотреть, работает ли это.
- Брандмауэр. Любая из сторон может блокировать связь tcp на уровне ОС. Отладка выполняется через Wireshark на Windows и tcpdump в unix. Начните снюхать, запустите свой код и посмотрите, что пошло не так. Скорее всего, вы увидите, что клиент отправляет SYN пакет, но сервер не сможет ответить с помощью пакета SYN|ACK . Если вы видите, что пакет SYN достигает сервера, попробуйте полностью завершить брандмауэр сервера и повторите попытку. Если нет, то клиенту запрещается исходящая связь (менее вероятно), и вам нужно будет отключить его брандмауэр.
- Использовать порт. Попробуйте удалить SO_REUSEADDR для отладки и посмотреть, что-то изменится.
- Исключения. Убедитесь, что вы не игнорируете какие-либо исключения из своих сокетов.
Ваш код работает отлично. Я внес некоторые незначительные исправления и объяснил их в комментариях внутри кода:
import socket from thread import * # 1.Gets the local ip/ip over LAN. HOST =socket.gethostbyname(socket.gethostname()) print HOST # 2.Use port no. above 1800 so it does not interfere with ports already in use. PORT =input ("Enter the PORT number (1 - 10,000)") s = socket.socket(socket.AF_INET, socket.SOCK_STREAM ) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) print "Socket Created" s.bind((HOST, PORT)) print "Socket Bind Complete" s.listen(10) print "Socket now listening" while True: connection, addr = s.accept() print "Connection Established!" connection.send("Welcome to the server. Type something and hit enter\n") while True: data = connection.recv(1024) if not data: break connection.sendall(data) print data connection.close() s.close()
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print "Socket Created" host = raw_input("HOST >>> ") # 3. Use the same port no. entered on server.py as the client binds to the # same port port = input ("Enter the PORT number (1 - 10,000)") s.connect((host, port)) while True: message = raw_input(">>> ") s.sendall(message) reply = s.recv(1024) print reply
Вышеприведенный код просто отлично работал для меня, я уверен, что это было бы и для меня, поскольку я испытал те же проблемы. Обнаруженные ошибки, я добавил их в комментарии внутри кода.
Как решить проблему с использованием сокетов в python?
Имеются две программы для передачи файлов по TCP-протоколу через интернет, клиент и сервер, все работало до того момента как переделал программы с использованием функций. Суть в том, что сервер три раза подряд отправляет клиенту информацию, клиент ее три раза должен принять, но получается одноразовое принятие всех трех запросов.
Это три склеенных вместе запроса.
import socket import os def open_server(): host = '0.0.0.0' port = 9091 serv_addr = (host, port) tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) tcp_socket.bind(serv_addr) tcp_socket.listen(1) print('Waiting connection') connection(tcp_socket) def connection(tcp_socket): conn, clnt_addr = tcp_socket.accept() print('Connection is established') data_to_recv = conn.recv(1024) if not data_to_recv: conn.close() tcp_socket.close() sys.exit(1) else: print('Client: '+data_to_recv) conn.send(b'Server to Client reporting') #Первый раз отсылаю информацию. transerf(conn, tcp_socket) def transerf(conn, tcp_socket): conn.send(str(os.path.getsize(os.path.dirname(__file__)+'list.dat'))) #Второй раз отсылаю информацию. fl = open(os.path.dirname(__file__)+'list.dat', 'rb') st = fl.read() conn.send(st) #Третий раз отсылаю информацию. conn.close() tcp_socket.close() def server(): open_server() server()
import socket import os def connection(): serv_addr = ('127.0.0.1', 9091) tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp_socket.connect(serv_addr) print('Connection is established') tcp_socket.send(b'Client to Server reporting') data_to_recv = tcp_socket.recv(1024) #Получаю первый запрос. print('Server: '+data_to_recv) transerf(tcp_socket) def transerf(tcp_socket): size = tcp_socket.recv(1024) #Второй раз получаю запрос. data = tcp_socket.recv(int(size)) #Третий раз получаю запрос. fl = open(os.path.dirname(__file__)+'list1.dat', 'w') fl.write(data) tcp_socket.close() def client(): connection() client()
Сокет не подключается Python
Вы не можете получить ни от кого, если сначала не приняли соединение через сокет. Поскольку это сокет TCP. Итак, ответ на другой вопрос должен решить вашу проблему.
Я пытался. Но это не сработало. Можете ли вы изменить код, который я упомянул в вопросе, и показать, что именно вы имеете в виду. Я получаю много ошибок после модификации. пожалуйста, дайте мне знать.
Подумайте об этом так, это сокет TCP. Таким образом, перед передачей данных необходимо установить соединение. Это означает, что клиентская программа должна запросить соединение с адресом сервера, и сервер должен его принять. Только после того, как принятие завершено, клиент может отправить данные на сервер, а сервер может получить отправленные данные recvfrom().
1 ответ
Прежде всего вам нужен код клиента для подключения к вашему серверу. Это сокет TCP, поэтому он ориентирован на соединение.
Это означает, что перед любой передачей данных (socket.recv (), socket.send ()) необходимо запросить соединение от клиента к серверу, а сервер должен принять соединение.
После установления соединения вы сможете свободно отправлять данные между сокетами.
Вот пример этого простого дизайна сокета, который может быть применен к вашей программе:
import socket # create an ipv4 (AF_INET) socket object using the tcp protocol (SOCK_STREAM) client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # connect the client # client.connect((target, port)) client.connect(('0.0.0.0', 9999)) # send some data (in this case a String) client.send('test data') # receive the response data (4096 is recommended buffer size) response = client.recv(4096) print(response)
import socket import threading bind_ip = '0.0.0.0' bind_port = 9999 max_connections = 5 #edit this to whatever number of connections you need server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((bind_ip, bind_port)) server.listen(max_connections) # max backlog of connections print (('Listening on <>:<>').format(bind_ip, bind_port)) def handle_client_connection(client_socket): request = client_socket.recv(4096 ) print (str(request)) client_socket.send('ACK!') client_socket.close() while True: client_sock, address = server.accept() print (('Accepted connection from <>:<>').format(address[0], address[1])) client_handler = threading.Thread( target=handle_client_connection, args=(client_sock,) # without comma you'd get a. TypeError: handle_client_connection() argument after * must be a sequence, not _socketobject ) client_handler.start()
Этот пример должен напечатать тестовые данные в консоли сервера и ACK! в клиентской консоли.
Редактировать: не уверен насчет отпечатков python3, работающих так, как я их написал здесь . но это лишь небольшая деталь. Общая идея — это то, что имеет значение в этом случае. Когда я доберусь до компьютера, я попытаюсь запустить его и исправить отпечатки, если есть какая-либо синтаксическая ошибка.
Почему мой сокет python не подключается к другому компьютеру?
Поэтому я недавно начал тестировать сокеты, и мне удалось создать сервер и клиент, которые работают вместе, когда я запускаю их на одном компьютере. Однако, когда я помещаю сервер на другой компьютер, он вызывает следующую ошибку: “” TimeoutError: [WinError 10060] Не удалось выполнить попытку подключения, потому что связанная сторона не ответила должным образом через какое-то время или установив соединение не удалось, подключенный хост не ответил “
import socket import pyautogui import os computerIP = socket.gethostbyname(socket.gethostname()) def Main(): host = computerIP port = 5000 value = 0 mySocket = socket.socket() mySocket.bind((host,port)) mySocket.listen(1) conn, addr = mySocket.accept() print ("Connection from: " + str(addr)) while True: data = conn.recv(1024).decode() if not data: break elif data == "shift": pyautogui.keyDown("shift") elif data == "relshift": pyautogui.keyUp("shift") elif data == "logout": os.popen("shutdown -l") elif data == "click": pyautogui.click() pyautogui.click() print ("from connected user: " + str(data)) data = str(data).upper() print ("sending: " + str(data)) conn.send(data.encode()) conn.close() if __name__ == '__main__': Main()
import socket def Main(): host = #same ip as server port = 5000 mySocket = socket.socket() mySocket.connect((host,port)) message = input(" -> ") while message != 'q': mySocket.send(message.encode()) data = mySocket.recv(1024).decode() print ('Received from server: ' + data) message = input(" -> ") mySocket.close() if __name__ == '__main__': Main()
ОС: Windows 8.1 Python verion: 3.4
Я попытался найти это в Интернете, но так как я довольно новичок в python, я не очень понял.
Скажите мне, есть ли что-нибудь, что мне нужно очистить.
Похоже, что порт заблокирован из-за какого-то брандмауэра.
Используйте socket.connect_ex() вместо socket.connect() . Если соединение будет успешным, оно вернет 0, в противном случае значение переменной errno поможет вам отладить причину сбоя соединения.
До подключения также используйте socket.settimeout() чтобы время соединения отсутствовало в заданном no. секунд.