I have already checked answers regarding my problem, but I couldn't find what's wrong. I am new to Python and that might be a problem. I have written this simple code to connect to a site, but I get this error:
socket.gaierror: [Errno 11004] getaddrinfo failed
This is my code:
import socket
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('http://www.py4e.com', 80))
mysock.send('GET http://www.py4e.com/code3/mbox-short.txt HTTP/1.0\n\n')
while True:
data = mysock.recv(512)
if(len(data) < 1):
break
print (data)
mysock.close()
import socket
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('www.py4e.com', 80))
mysock.send('GET http://www.py4e.com/code3/mbox-short.txt HTTP/1.0\n\n')
while True:
data = mysock.recv(512)
if(len(data) < 1):
break
print (data)
mysock.close()
Quite simple, don't use http:// in your host declaration on .connect().
http:// is a protocol and www.py4e.com is a host (or A record in a DNS server). The standard socket library doesn't know anything regarding protocols and there for requires only a host and a port number.
If you want automated processes check out urllib.request or #Mego's answer using Requests which handles the connection and HTTP parsing for you.
Also if you're using Python3 which you probably should, you need to send bytes data when doing .send().
There's two ways of converting your string to bytes data:
mysock.send(b'GET http://www.py4e.com/code3/mbox-short.txt HTTP/1.0\n\n')
mysock.send(bytes('GET http://www.py4e.com/code3/mbox-short.txt HTTP/1.0\n\n', 'UTF-8'))
Both does the same thing basically.
Finally, in a GET request you don't request http:// either.
Instead you just send the path to the file you want to retrieve:
mysock.send(b'GET /code3/mbox-short.txt HTTP/1.0\n\n')
The reason is (again) that http:// is a protocol descriptor and not part of the actual protocol data being sent. You also don't need the host declaration in your GET request because the server that you connected to already knows which host you're on - since you're... connected to it.
Instead the server expects you to supply a Host: <hostname>\r\n header if the host is serving multiple virtual hosts.
You might need a few other headers tho to be able to request actual content from certain web-servers.
But this is the basic jist of things.
Continue reading
Here's a good start:
https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Client_request
It shows you what a raw GET request looks like.
An in the future I recommend using your browsers built-in Network Debugger which can show raw headers, raw responses and a whole bunch of other things.
Related
I'm reading about socket module in a web learning site about python, they gave us a simple steps to use socket module like follows:
import socket
with socket.socket() as client_socket:
hostname = '127.0.0.1'
port = 9090
address = (hostname, port)
client_socket.connect(address)
data = 'Wake up, Neo'
data = data.encode()
client_socket.send(data)
response = client_socket.recv(1024)
response = response.decode()
print(response)
when executing I got the error message:
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it.
when I searched about this some sites was talking about server listening and I see in most of tutorials about server socket and they use it along with client one.
so Is the error message related to the fact that I'm not using a server socket and is it a must to use them both
Update:
after reading the answers I got, I went to the test.py file that the course instructors use to evaluate our codes and I see that they make the server socket in it , so the server is already made by them. that take me back to the Error I got why does it happen then.
def server(self):
'''function - creating a server and answering clients'''
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind(('localhost', 9090))
self.ready = True
try:
self.sock.listen(1)
conn, addr = self.sock.accept()
self.connected = True
conn.settimeout(15)
while True:
data = conn.recv(1024)
self.message.append(data.decode('utf8'))
if len(self.message) > 1_000_000:
conn.send(
json.dumps({
'result': 'Too many attempts to connect!'
}).encode('utf8'))
break
if not data:
break
Each connection requires a client, which initiates the connection, and a server, which listens for the incoming connection from the client. The code you have shown is for the client end of the connection. In order for this to run successfully you will need a server listening for the connection you are trying to create.
In the code you showed us you have the lines
hostname = '127.0.0.1'
port = 9090
address = (hostname, port)
client_socket.connect(address)
These are the lines that define what server you are connecting to. In this case it is a server at 127.0.0.1 (which is localhost, the same machine you are running the code on) listening on port 9090.
If you want to make your own server then you can look at the documentation for Python sockets and the particular functions you want to know about are bind, listen, and accept. You can find examples at the bottom of that same page.
Given that you appear to have found this code as part of a course, I suspect they may provide you with matching server code at some point in order to be able to use this example.
For a school assignment, I am required to fill in the blanks of a sample Python 3 application that acts as a simple proxy server. I am required to only use the socket library.
My question lies in the fact that I was not taught how to pull the url of a request from a client, nor can I find information online to help me. Here's the code thus far (I'm including them to give an example of the style of Python I'll need to have written):
from socket import socket, gethostname, AF_INET, SOCK_STREAM
import sys
if len(sys.argv) <= 1:
print ("Usage : 'python ProxyServer.py server_ip'\nserver_ip : It is the IP Address Of Proxy Server")
sys.exit(2)
# Create a server socket, bind it to a port and start listening
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(('localhost', 8888))
tcpSerSock.listen(5)
while 1:
# Start receiving data from the client
print ('Ready to serve...' )
tcpCliSock, addr = tcpSerSock.accept()
print ('Received a connection from:', addr)
message = addr
print (message.value)
# Extract the filename from the given message
filename = message.split()[1].partition("/")[2]
print (filename)
When I go to queue the page, I navigate to 'localhost: 8080/www.google.com/'.
My question is, how in Python would I be able to read in 'www.google.com' as a string from the queued URL?
This was the answer I found.
tcpCliSock.recv(4096)
^ The above returns a bytes object that contains the full request. When converted to a string and split based on spaces, the 'www.google.com' segment of the request is at position [1].
Off the top of my head, retrieving the URL would look like this:
test = message.split()[1]
So I am very new to Python and am now trying to understand how to send a request using TCP in Python. The sample code and document is not very helpful (to me, as I don't understand Java).
The document:
https://www.sharekhan.com/Upload/General/TradeTigerAPIForClient.pdf
I have the following till now
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server = '192.168.43.211'
port = 800
request = "DataLength = 196|Transcode = 1|LoginId = ***|MemberPassword = sh*|TradingPassword = S77*| IP = 192.618.31.211|Reserved = |"
s.connect((server,port))
s.send(request.encode())
result = s.recv(4096)
If I use this the program shows I am connected and the result is b''
I also tried
request = "|DataLength =108|Transcode = 21|Exchange Code=NC|Reserved=|"
result is b'Hurray you are connected'
How do I use the commands from the document to get data?
According to this, you can send a TCP packet like this:
import socket
server = '192.168.31.211'
port = 80
buffer_size = 4096
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((server, port))
sock.send(message)
data = sock.recv(buffer_size)
sock.close()
Note I didn't include your message here, nor did I encode your data. However, as was pointed out in the comments, your IP address is incorrectly written and refers to a private IP address, according to the IANA so if you're trying to send out over a public network, this won't work. Additionally, I have noticed a couple of other problems with your code:
Your message looks like you've manually included TCP header information. Be aware that by using the socket library the way you are and the way I have suggested, you are making a TCP request. The header information will therefore be included with your request so you don't need to include it yourself.
What you have here is the client code and you didn't include any server code. Have you written code for your server? If not, you'll need some.
Otherwise, I can't see any problems with your code.
I am trying to make a python webserver listening to localhost on port 8080. So far I can only setup the connection, I don't know how to get the getrequest from the browser? When I go to : http://localhost:8080/example.txt it should display the txt file in the browser. But how do I get the get request ?
This is my code so far:
host = ''
port = 8080
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((host, port))
sock.listen(1)
while 1:
csock, caddr = sock.accept()
cfile = csock.makefile('rw', 0)
Thanks!
Please read HTTP specifications (e.g. IETF RFC 2616 - it's some obsoleted but good for initial reading). Generally, after accept(), you should
read input until empty line is got (in other words, CRLF CRLF sequence is seen in input)
split input into lines, combine them to header fields
process header fields you need to look into for satisfying a request
read request entity, if any
form response and send it
For an initial implementation, you can omit dealing with many extended issues as: DoS by request size security, chunked and other non-plain transfer encodings, multiple hosts, etc.
OTOH, if this isn't a homework, better is to use stock BaseHTTPServer module for a concept, and then consider following moving to more advanced implementation.
I'm trying to write a python web server using the socket library. I've been through several sources and can't figure out why the code I've written doesn't work. Others have run very similar code and claim it works. I'm new to python so I might be missing something simple.
The only way it will work now is I send the data variable back to the client. The browser prints the original GET request. When I try to send an HTTP response, the connection times out.
import socket
##Creates several variables, including the host name, the port to use
##the size of a transmission, and how many requests can be handled at once
host = ''
port = 8080
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
while 1:
client, address = s.accept()
data = client.recv(16)
if data:
client.send('HTTP/1.0 200 OK\r\n')
client.send("Content-Type: text/html\r\n\r\n")
client.send('<html><body><h1>Hello World</body></html>')
client.close()
s.close()
You need to consume the input before responding, and you shouldn't close the socket in your while loop:
Replace client.recv(16) with client.recv(size), to consume the request.
Move your last line, s.close() back one indent, so that it is not in your while loop. At the moment you are closing the connection, then trying to accept from it again, so your server will crash after the first request.
Unless you are doing this as an exercise, you should extend SimpleHTTPServer instead of using sockets directly.
Also, adding this line after your create the socket (before bind) fixes any "Address already in use" errors you might be getting.
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Good luck!