I am trying to control some test equipment with a TCP connection. The equipment comes with software that you are able to control over TCP. Basically, you can input the IP address and port of the client computer and there is also an indicator light that shows when there is an open listening session on that port (this is all on the equipment software interface)
I have tested this using SocketTest3 (free software) and am able to start a listening session as well as send commands from another computer. Now, I want to control the equipment with Python. I am running the code for the server and client on the same machine as the test equipment (using local IP address). When I simply run the code (with the equipment software closed) I am able to send, receive, and print the messages I send. When I have the equipment software open (necessary for control) I am able to start a listening session (indicator light shows up on equipment software), but nothing happens (no errors and nothing received) when I send commands. The messages are also not sent back to the client to print.
Any ideas? It's probably something very simple that I'm missing.
Server code:
import sys
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
TCP_IP = '127.0.0.1'
TCP_PORT = 8001
s.bind((TCP_IP, TCP_PORT))
s.listen(5)
connection, client_address = s.accept()
BUFFER_SIZE = 20
print 'Address: ', client_address
while 1:
print "receiving..."
data = connection.recv(BUFFER_SIZE)
print data
if not data: break
print "received data:", data
connection.send(data) # echo
connection.close()
Client code:
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 8001
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
print "sending message..."
s.sendall('ST<CR>') # Send command
print "receiving message..."
data = s.recv(BUFFER_SIZE)
s.close()
print "received data:", data
For those wondering what is missing from camerausb's code, I think he was not seeing anything from the client's print statement because he did not use repr() to format the data. I had a similar problem, but this worked for me:
print 'Received', repr(data)
Related
I have created a simple python server that sends back everything it receives.
I wonder if it would be possible to close the connection immediately after sending the data to the client (web browser), and the client then displays the data it has received. Currently, the client displays The connection was reset.
Thanks
#!/user/bin/env python3
import socket
HOST = 'localhost' # loopback interface address
PORT = 3000 # non-privileged ports are > 1023
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
while True:
# connect to the next client in queue
conn, addr = s.accept()
with conn:
print('Connected by', addr)
data = conn.recv(1024).decode()
print(data)
conn.sendall(data.encode())
Solution
#!/user/bin/env python3
import socket
HOST = 'localhost' # loopback interface address
PORT = 3000 # non-privileged ports are > 1023
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
while True:
# connect to the next client in queue
conn, addr = s.accept()
print('Connected by', addr)
data = conn.recv(1024).decode()
print(data)
conn.sendall(data.encode())
conn.shutdown(socket.SHUT_WR) # changed
Explanation
The solution uses conn.shutdown(socket.SHUT_WR) which sends a FIN signal instead of conn.close() which sends a RST signal.
We don't want to force the connection to close. TCP setup is expensive, so the browser would ask the server to keep the connection alive to query assets, and in this example the browser asks for style.css.
RST confuses the browser, and Firefox will show you "connection reset" error.
FIN says: "I finished talking to you, but I'll still listen to everything you have to say until you say that you're done."
RST says: "There is no conversation. I won't say anything and I won't listen to anything you say."
from FIN vs RST in TCP connections
Here is the Wireshark capture of using shutdown, we see that both the server at 3000 and the browser acknowledged each other's FIN.
When using close, we see that
A better option would be to wait for the client to initiate the 4 way finalization by programming the server to shut down the socket when the client signals FIN.
The 4 way finalization
From https://www.geeksforgeeks.org/tcp-connection-termination/
Im trying to send a messages from the server to the client
I tried deleting the .close and puting a while loop on print but it still doesn't won't to work
Client
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.connect((host, port))
while True:
print (s.recv(1024))
Server
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print ('Got connection from', addr)
x = str(input("ënter a message"))
data = x.encode()
c.send(data)
I expect the output to be 2 messages from the server but it is only sending 1 and then closing the connection
Switch your accept and while True: lines. Once you accept a connection, keep sending on the same connection.
Note that TCP is a streaming protocol. There is no concept of "messages", but just a bunch of bytes. If you send fast enough, such as:
c.send(b'abc')
c.send(b'def')
then recv(1024) could receive b'abcdef'. For more complex communication, you'll have to define a protocol and buffer recv until you are sure you have a complete message. A simple way in this case is read until you find a newline, or send a byte (or more) indicating the size of the total message before sending the actual message.
I am building a simple network chat in Python using UDP, however, when I run the server code on one machine and the client on another, no message is received by the server and no message is sent back to the client by the server script. Here is my code:
Server:
import socket, sys
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', 9997)) #need higher port
while True:
x = raw_input("Enter your message: ")
sent = sock.sendto(x, ('', 9997))
data, address = sock.recvfrom(4096)
print data, " ", address
sock.close()
Client:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
print "Waiting to receive"
data, server = sock.recvfrom(4096)
print data
x = raw_input("Enter message: ")
sent = sock.sendto(x, server)
sock.close()
Does anyone know what I am doing wrong here? Is is possible that code is fine, but the UDP is not reliable enough and is dropping the message?
As I said, since your code seems a little unclear (to me, at least), I'm posting you a very similar working example.
Here's the Server:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address = ('localhost', 1932)
sock.bind(server_address)
BUFFER_SIZE = 4096
try:
while True:
data, address = sock.recvfrom(BUFFER_SIZE)
print "Client sends: ", data
reply = raw_input("Your response:\n")
sock.sendto(reply,address)
except KeyboardInterrupt:
sock.close()
The server creates a socket and binds it to its address and the port it's listening to, 1932 in our case. He waits for an incoming message, asks for a reply, then sends it back to the sender.
Here's the Client:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_address = ('localhost', 1931)
server_address = ('localhost', 1932)
sock.bind(client_address)
BUFFER_SIZE = 4096
try:
first_msg = raw_input("Your first message:\n")
sock.sendto(first_msg,server_address)
while True:
data, address = sock.recvfrom(BUFFER_SIZE)
print "Client sends: ", data
reply = raw_input("Your response:\n")
sock.sendto(reply,address)
except KeyboardInterrupt:
sock.close()
It's very similar to the server, the only difference is that it sends a message before the while loop, in order to start the conversation. Then it just enters the receive/reply loop, just as the server does. It has the server address too, that is different (different port, since I'm on localhost)
The try/catch block is here just to close gracefully the whole process.
I used localhost and different ports on my computer and tested it, and it works. You should just change the addresses to get it working over LAN, and you could keep the same port if the addresses are different, it should work.
Two computers in a LAN connecting to a wireless router, one IP address is 192.168.1.106 (server), the other one is 192.168.1.107 (client), the gateway on both computer is 192.168.1.1 (the router itself).
The two computer can ping each in two directions which means there should be no problem with routing and the router itself. But I failed when I tried to use Python UDP socket, the server cannot get any information from the client, and same happened when I change the ip address. (But it works fine when server and client are on a same computer using local ip address, so the code is should be ok)
I am using the following code:
server:
import socket
address = ('192.168.1.106', 5678) # the server listening on address 192.168.1.106
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(address)
while True:
data, addr = s.recvfrom(2048)
if data == "empty":
print "no data from client"
else:
print "received:", data, "from", addr
s.close()
client:
import socket
address = ('192.168.1.106', 5678) # the client send to address 192.168.1.106
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
msg = raw_input()
if not msg:
msg = "empty"
s.sendto(msg, address)
s.close()
Did you open the UDP port on the firewall on both comoutera?
I'm trying to take incoming data from one port and stream it to a port on another computer. Here is what I have so far:
import socket
port = 8787
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("", port))
print ("waiting on port:", port)
while 1:
data, addr = s.recvfrom(1024)
print (data)
`
So I can stream the data in from the port using the script above no problem. What I need to do is now take that data stream and forward it to a port on another computer. I came across this:
#!/usr/bin/python
from socket import *
bufsize = 1024 # Modify to suit your needs
targetHost = "192.1.1.2"
listenPort = 8788
def forward(data, port):
print "Forwarding: '%s' from port %s" % (data, port)
sock = socket(AF_INET, SOCK_DGRAM)
sock.bind(("localhost", port)) # Bind to the port data came in on
sock.sendto(data, (targetHost, listenPort))
def listen(host, port):
listenSocket = socket(AF_INET, SOCK_DGRAM)
listenSocket.bind((host, port))
while True:
data, addr = listenSocket.recvfrom(bufsize)
forward(data, addr[1]) # data and port
listen("localhost", listenPort)
But I'm not sure where to put the outgoing port. The IP for the home server that I'm pulling data on has an IP of say 192.1.1.1 and is streaming data in from port 8787. The remote server has an IP of say 192.1.1.2 and it's listening on port 8788. I'm not sure where I need to put port 8787, which is where the home server is pulling in the data from. Any suggestions would be most helpful. Thanks!
If that last code you quoted runs on your 192.1.1.1, you need to call listen("localhost", 8787) in the last line instead of listen("localhost", listenPort), and you should be fine. listenPort refers to the port where the server that the data is being forwarded to (192.1.1.2) is listening, while listen expects the port where the current machine (192.1.1.1) listens for input. listen then calls forward (telling it to use the same port for the outgoing connection).