from socket import *
from time import ctime
HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
while True:
print 'waiting for connection...'
tcpCliSock, addr = tcpSerSock.accept()
print "...connected from:", addr
while True:
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
tcpCliSock.send("[%s] %s" % (ctime(), data))
tcpCliSock.close()
tcpSerSock.close()
I got quite some errors cleared them. I am following the Core Python Application book. I need to know what happens in the loop?
tcpCliSock, addr = tcpSerSock.accept()
what does this line of code do exactly?
'waiting for connection?' with whom and how? there are no other parameters given to connect with something!
How exactly does this listen() work?
Explain the program in short.
Thank you
What you want is described in the Python Sockets HOWTO in the documentation. Here's the Python 2 version:
http://docs.python.org/2/howto/sockets.html
The short version is that the code you posted is a simple server that is configured to respond to requests from a separate process, possibly on a different machine, that sends a small chunk of data to it. This server sends back the data with a time stamp in front.
socket.listen() is used to set up a socket to receive incoming connections. The connection requests go into a short queue and are handled in order. socket.accept() checks to see if there's an incoming connection in that listen queue, and if so, it opens up a new socket to the other machine just to handle that one connection. When the connection ends, the new socket to the first client closes and the server socket moves on to the next connection in the queue to handle it.
To make this server do anything, you'd need to use some client program to open the correct port and send a message to it. For something this simple, you might try using telnet if it's installed on your machine. Run this server, then try:
telnet localhost 21567
on the same machine and start typing some text. You should see responses. My output looked like this:
$ telnet localhost 21567
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
j
[Sun Sep 15 11:58:27 2013] j
jkl
[Sun Sep 15 11:58:29 2013] jkl
fdjksla;
[Sun Sep 15 11:58:30 2013] fdjksla;
fdjkasl;fjdksal;fjkdsa;
[Sun Sep 15 11:58:32 2013] fdjkasl;fjdksal;fjkdsa;
NOTE: You will have to put a hostname into your HOST field for this to work. Try 'localhost' and see if that helps. Also, I believe if you use localhost as your HOST parameter you may not be able to receive connections from other machines. In that instance, you'll need to use your own local hostname or IP address on the network.
I've edited the OP with fixed indenting and 'localhost' for the HOST parameter, and tested that this works with telnet in another shell as I've described here.
I notice also that this code never reaches the close() for the server socket. You'd want a break somewhere in your outer while loop if you wanted to close your server and exit in an orderly way.
Related
*Before you mark as duplicate please note that I am referencing this similar question found here:
Python Socket Programming - ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
unfortunately but have found anything in that post that provides a solution to my problem.
I am working on a very basic exercise designed to familiarize students with programming related to networks. This particular assignment is a common one as is described as follows:
In this assignment, you will learn the basics of socket programming for TCP connections in Python: how to create a socket, bind it to a specific address and port, as well as send and receive an HTTP packet. You will also learn some basics of HTTP header format. You can only use Python3.
You will develop a web server that handles one HTTP request at a time. Your web server should accept and parse the HTTP request, get the requested file from the server’s file system, create an HTTP response message consisting of the requested file preceded by header lines, and then send the response directly to the client. If the requested file is not present in the server, the server should send an HTTP “404 Not Found” message back to the client.
Part one specification:
Put the attached HTML file (named HelloWorld.html) in the same directory in which the server webserver.py runs. Run the server program. Determine the IP address of the host that is running the server (e.g., 128.238.251.26 or localhost). From another host, open a browser and provide the corresponding URL. For example: http://128.238.251.26:6789/HelloWorld.html. You can open a browser in the same host where the server runs and use the following http://localhost:6789/HelloWorld.html.
‘HelloWorld.html’ is the name of the file you placed in the server directory. Note also the use of the port number after the colon. You need to replace this port number with the port number that was assigned to you. In the above example, we have used port number 6789. The browser should then display the contents of HelloWorld.html. If you omit “:6789”, the browser will assume port 80 (why?), and you will get the web page from the server only if your server is listening at port 80.
Then try to get a file that is not present on the server (e.g., test.html). You should get a “404 File Not Found” message.
Part Two specification:
Write your own HTTP client to test your server. Your client will connect to the server using a TCP connection, send an HTTP request to the server, and display the server response as an output. You can assume that the HTTP request sent is a GET method. The client should take command line arguments specifying the server IP address or hostname, the port at which the server is listening, and the HTTP file name (e.g., test.html or HelloWorld.html). The following is an input command format to run the client. webclient.py <server_host> <server_port>
My code is for the Webserver is as follows:
#import socket module
from socket import *
import sys # In order to terminate the program
serverSocket = socket(AF_INET, SOCK_STREAM)
# Prepare a sever socket
# Fill in start
serverHost = '192.168.1.4'
serverPort = 56014
serverSocket.bind((serverHost, serverPort))
serverSocket.listen(5)
# Fill in end
while True:
#establish connection
print('The server is ready to receive')
connectionSocket, addr = serverSocket.accept() # Fill in start #Fill in end
try:
message = connectionSocket.recv(4096) # Fill in start #Fill in end
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.readlines() # Fill in start #Fill in end
# send one http header line in to the socket
# Fill in start
connectionSocket.send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n")
connectionSocket.send("\r\n")
# Fill in end
# Send the content of the requested file to the connection socket
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i].encode())
connectionSocket.send("\r\n".encode())
connectionSocket.close()
except IOError:
# Send HTTP response code and message for file not found
# Fill in start
connectionSocket.send("HTTP/1.1 404 Not Found\r\n")
connectionSocket.send("Content-Type: text/html\r\n")
connectionSocket.send("\r\n")
connectionSocket.send("<html><head></head><body><h1>404 Not Found</h1></body></html><\r\n>")
# Fill in end
# Close the client connection socket
# Fill in start
serverSocket.close()
# Fill in end
serverSocket.close()
sys.exit() # Terminate the program after sending the corresponding data
My code for the Webclient is as follows:
from socket import *
import sys
serverName = sys.argv[1]
serverPort = int(sys.argv[2])
fileName = sys.argv[3]
request = "GET "+str(fileName)+" HTTP/1.1"
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
clientSocket.send(request.encode())
returnFromSever = clientSocket.recv(4096)
while(len(returnFromSever)>0):
print(returnFromSever.decode())
returnFromSever = clientSocket.recv(4096)
clientSocket.close()
The error I am receiving is:
"No connection could be made because the target machine actively refused it"
Admittedly, I know almost nothing about network related programming and on top of that I am not familiar with the Python syntax (my entire degree program was exclusively in Java) so I am very lost here and somewhat desperate.
If anyone could please point me in the right direction as far as how to correct this error, I would be very deeply grateful.
Thanks
The error you are getting (No connection could be made because the target machine actively refused it) means that the port you are trying to connect to is not not being listened on the server.
For example, if you try to connect to 192.168.1.1:80 (IP = 192.168.1.1, port=80) and the server on 192.168.1.1 doesn't listen on port 80, you would receive this error.
A few things I would check in your case:
Is your server IP actually 192.168.1.4 ? If not, set it to the correct IP of the interface you want to listen on. If you want to listen on all the interfaces of the server, use this: serverHost = '0.0.0.0'
Does your client code attempt to connect to the server port? The server port is 56014. You need to pass it as the second parameter of your client program (because of this line serverPort = int(sys.argv[2])).
I have an extremely simple tcp server in python the code for which is below:
#!/usr/bin/env python
import socket
sock = socket.socket()
sock.bind(('',3912))
sock.listen(100)
num_cons = 10
cons = []
for i in range(num_cons):
con, addr = sock.accept()
cons.append(con)
while True:
for con in cons:
msg = "a"* 1000
num_sent = con.send(msg.encode())
print("sent: {} bytes of msg:{}".format(str(num_sent), msg))
The corresponding client code is
#!/usr/bin/env python
import socket
sock = socket.socket()
sock.connect(('',3912)) # in reality here I use the IP of the host where
# I run the server since I launch the clients on a different host
while True:
data = sock.recv(1000)
print("received data: {} ".format(str(data)))
Now, if I start the server with
./server.py
and 10 clients in parallel from a different host:
for i in `seq 1 10`; do ./client.py 2>/dev/null 1>/dev/null & done
And I send kill -SIGSTOP %1 to the first client, I expect the server to successfully keep trying to send data because it cannot know that the client has been stopped. Instead, the server blocks when it tries to send the data to client 1. I can understand the behaviour if the clients were on the same host as the server: we tried to write data, but the kernel buffers are full, so we block in the server, but the client never reads, so the buffer is never freed. However, if the clients are on a different machine, the kernel buffers of the server host should only be full temporarily and then the kernel should send the data over the network card and free them. So why is my server blocking on the send call? I have not verified if the same behaviour is seen when using a different language (C for example)
It is weird because 1000 characters is a small size for TCP. I have no available Linux machine but on a FreeBSD box, I could successfully send 130000 bytes on a TCP connection where the peer was stopped before the sender blocks. And more that 1000000 on Windows.
But as TCP is a connected protocol, a send call will block if it cannot queue its data because the internal TCP stack queue is full.
The gist of your problem seems to be that you're creating a SOCK_STREAM socket (i.e. TCP), and then abruptly terminating the client. As discussed in the Python Socket Programming HOWTO, a hang is expected in this situation.
TCP is a reliable protocol, meaning that every transmitted packet has to be acked. If the receiving side is dead, the sender will block waiting for that acknowledgement. Try setting a timeout and see if your send raises a socket.timeout after the expected time.
I have this program which is for now supposed to only listen on port 80 and receive data either from browser connections or from another python scripts.
this code:
import socket # Import socket module
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname() # Get local machine name
port = 80 # Reserve a port for your service.
s.bind(("192.168.252.7", port)) # Bind to the port
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
print c.recv(1024)
c.close() # Close the connection
which is all copied from tutorialspoint. This code receives data, when the port is set to anything but 80 (eg 8080, 12345), but when it is 80, it only accepts the client but seems to not receive any data despite the data being successfully sent from somewhere else....
PLEASE HELP GUYS
Port 80 and all ports <1024 are privileged ports, your program must run as root in order to properly bind to these ports. I'm guessing you are running on Windows, since on any unix calling s.bind(("127.0.0.1", 80)) results in PermissionError: [Errno 13] Permission denied exception immediately.
I'm not sure how Windows deals with priveleged ports, but quick google search points towards windows firewall messing with your program.
Proper web servers, such as Nginx or Apache, start as root, bind to the port 80 and immediately drop to a less privileged user, since running under root is dangerous.
P.S.: A couple of suggestions:
You can skip the socket.gethostname(). Use ip 127.0.0.1 if you want your program to be accessible only from your machine, or use ip 0.0.0.0 if you want to be accessible from any machine on your network.
You should try to switch to Python 3 ASAP, since Python 2 is basically dead at this point. Don't get used to two's syntax, you gonna relearn it in a couple of years tops.
So you have a basic understanding of the parts im using, I have:
Arduino Uno
Seeed Studio GPRS Shield v2.0 (http://www.seeedstudio.com/wiki/GPRS_Shield_V2.0)
Ultimate GPS for Adafruit V3.3 (https://www.adafruit.com/products/746?gclid=Cj0KEQjw3-W5BRCymr_7r7SFt8cBEiQAsLtM8qn4SCfVWIvAwW-x9Mu-FLeB6hLmVd0PAPVU8IAXXPgaAtaC8P8HAQ)
Here is my problem:
I have tested the Arduino stacked with the GPRS shield, and it works fine with regards to accessing the internet through TCP, sending SMS, etc.. However, my application requires me to send GPS data from the adafruit GPS to a web server that I have already coded with Django and postgresql. The backend is set up.
I need to send the data from the Uno (client) to my laptop (server), which I coded in python (This is just to check whether it is creating a connection):
#!/usr/bin/env python
import socket
# import postgres database functions
TCP_IP = '192.168.1.112'
TCP_PORT = 10000
BUFFER_SIZE = 40
server_address = (TCP_IP,TCP_PORT)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created.'
# Bind socket to TCP server and port
try:
s.bind(server_address)
except socket.error as msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket Bind Complete.'
# Start Listening on socket
s.listen(1) # Puts socket into server mode
print 'Listening on port: ', TCP_PORT
# Now Keep Talking with the client
while (1):
# Wait to accept a connection
conn, addr = s.accept() # Wait for incoming connection with accept()
print 'Connection address:', addr
data = conn.recv(BUFFER_SIZE)
if not data: break
print "recieved data: data", data
conn.send(data) #echo
conn.close()
I dont think there is a problem with this. From this I will post data to my postgreSQL database. However, When I try to use AT commands on the SIM900 module to connect to the server using port 10000, I cannot connect:
AT+CIPSHUT
SHUT OK
AT+CGATT?
+CGATT: 1
OK
AT+CIPMUX=0
OK
AT+CSTT="fast.t-mobile.com","",""
OK
AT+CIICR
OK
AT+CIFSR
6.60.94.49
AT+CIPSTART="TCP","192.168.1.112,"10000"
OK
STATE: TCP CLOSED
CONNECT FAIL
I have tried connecting through TCP and replaced the AT+CIPSTART line with the below statement and it worked, so I know TCP works:
AT+CIPSTART="TCP","www.vishnusharma.com", "80"
Is the IP i'm using wrong? I'm new to this, but if it makes a difference, im using Ubuntu 16.04 partitioned on my Mac OSX. I have also checked the APN for T-mobile and it seems fine.
Any help would be greatly appreciated. Thank You!
The IP you're using is inside a NAT since it starts with 192.168. Unless you have a private apn with the mobile operator you're using, you won't be able to reach your Ubuntu from a public IP. Your ISP gives you a public IP address which ir administrated by your router, so if you want this to work, you'll have to do a port forwarding from your router to your Ubuntu.
To do the port forwarding you have to get in the router's configuration page (Typically 192.168.1.1 but depends on the model) an there you'll have to redirect the port XXX to 192.168.1.112:10000. After that you have to obtain your public IP (curl ifconfig.co) and use it to access from the SIM900.
First of all as a suggestion, you can combine the two shields by using SIM908 (unless you are getting more precision on your GPS shield). Since your TCP connection is working, I bet that the port 10000 on your ubuntu is blocked by the firewall. You can first try to turn off your firewall and see if it works. If it did not worked its something else. If it worked, turn on your firewall and then unblock the tcp port using the following command:
sudo ufw allow 10000/tcp
I have the server bind to a particular port:
serv_sock = socket(AF_INET, SOCK_STREAM)
serv_sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
serv_sock.bind((gethostname(), MAGIC_FLOW_PORT))
serv_sock.listen(MAX_MAGIC_FLOWS)
while True:
(client_sock, address) = serv_sock.accept()
print "Accepted a flow"
And the client does this:
client_sock = socket(AF_INET, SOCK_STREAM)
client_sock.bind((gethostname(), MAGIC_FLOW_PORT+1))
client_sock.connect((server_ip, MAGIC_FLOW_PORT))
while True:
client_socket.send("ABCDEF")
time.sleep(5)
So the expectation is client sends a TCP/IP packet with src port MAGIC_FLOW_PORT+1 and dst port MAGIC_FLOW_PORT every 5 seconds.
I enabled tcpdump in the server and I can see the packet as expected every 5s. However, the server prints the "Accepted a flow" only once, and nothing after that.
However if I comment this line in the client socket:
client_sock.bind((gethostname(), MAGIC_FLOW_PORT+1))
client then generates a packet with a different src port every time and the server accepts that. I also tried the server with
serv_sock.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
I still don't the second packet picked up the server.
Can I connect with the same src IP/port multiple times to the same server?
Thanks
Binding to a certain port should always work if you have the permissions to do so (<1024 you need to be root) and no other socket is inhabiting the same port on the same interface.
Except, if you use SO_REUSEPORT, then you can bind multiple listening sockets to the same port.
Just think about it, how would the server side know where to send the reply? (Assuming no anycast routing magic here.)
If you comment out that client_sock.bind() then the kernel picks a free port as the source of your connection, so that explains why the port is different after every connect().
The counterpart of the server's accept() is the client's connect(), not send(). So you should get an accept() call to return every time some other socket connects to that listening socket. If you want to react to received messages you should use client_sock.recv(). (Docs).