python webserver socket programming error - python

# Import socket module
from socket import *
#from socket import AF_INET, SOCK_STREAM, socket
import sys # In order to terminate the program
# Create a TCP server socket
#(AF_INET is used for IPv4 protocols)
#(SOCK_STREAM is used for TCP)
ipadress=socket.gethostbyname(socket.gethostname())
subnetAdress = '.'.join(ipadress.split('.')[:3]) + '.0'
print(f"ipadress : {ipaddress}")
print(f"subnetAdress : {subnetAdress}")
file = open("permit.txt", 'r', encoding="UTF-8")
permitList = file.readlines()
#
serverSocket = socket(AF_INET, SOCK_STREAM)
# Assign a port number
serverPort = 6789
# Bind the socket to server address and server port
serverSocket.bind(("", serverPort))
# Listen to at most 1 connection at a time
serverSocket.listen(1)
# Server should be up and running and listening to the incoming connections
while True:
print('The server is ready to receive')
# Set up a new connection from the client
connectionSocket, addr = serverSocket.accept()
# If an exception occurs during the execution of try clause
# # the rest of the clause is skipped
# # If the exception type matches the word after except
# # the except clause is execute
if subnetAdress+'\n' in permitList:
print("Warning!!\n it's not permitted")
continue
try:
# Receives the request message from the client
message = connectionSocket.recv(1024).decode()
print(message)
# Extract the path of the requested object from the message
# # # The path is the second part of HTTP header, identified by [1]
# filename = message.split()[1]
print(filename)
# Because the extracted path of the HTTP request includes
# # # a character '\', we read the path from the second character
file = open(filename[1:], 'rb')
# Store the entire contenet of the requested file in a temporary buffer
# outputdata = file.read()
# # Send the HTTP response header line to the connection socket
header = 'HTTP/1.1 200 OK\n'
if(filename.endswith(".jpg")):
filetype = 'image/jpg'
elif(filename.endswith(".mp4")):
filetype = 'video/mp4'
elif(filename.endswith(".wmv")):
filetype = 'video/wmv'
elif(filename.endswith(".gif")):
filetype = 'video/gif'
elif(filename.endswith(".html")):
filetype = 'text/html'
else:
raise IOError
header += 'Content-Type: '+str(filetype)+'\n\n'
print(header)
connectionSocket.send(header.encode())
# 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(outputdata)
connectionSocket.send("\r\n".encode())
# Close the client connection socket
# connectionSocket.close()
except IOError:
# Send HTTP response message for file not found
header = 'HTTP/1.1 404 Not Found \n\n'
connectionSocket.send(header.encode())
connectionSocket.send(
"<html><head></head><body><h1>404 Not Found</h1></body></html>\r\n".encode())
# Close the client connection socket
connectionSocket.close()
serverSocket.close()
sys.exit()
#Terminate the program after sending the corresponding data
I did this for socket programming
it's hard to explain but I had this error. and I put from socket import
please help me out. I don't know why
I will be dying ..
AttributeError Traceback (most recent call last)
c:\Users\taek\python\탐색\네트워크\과제3\IPwebServer.py in <module>
9 #(SOCK_STREAM is used for TCP)
10
---> 11 ipadress=socket.gethostbyname(socket.gethostname())
12 subnetAdress = '.'.join(ipadress.split('.')[:3]) + '.0'
13
AttributeError: type object 'socket' has no attribute 'gethostbyname'
** **
ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ

If you use
from socket import *
then you have to use without socket.
gethostbyname(...)
gethostname()
socket(AF_INET, SOCK_STREAM)
If you use
import socket
then you have to use with socket.
socket.gethostbyname(...)
socket.gethostname()
socket.socket(AF_INET, SOCK_STREAM)
BTW: import * is not preferred - see PEP 8 -- Style Guide for Python Code

Related

Sending a file over TCP connection

I want to send i file over TCP but when i try to run this the connection fails, the server receives the file but it gives this error: ERROR: Client timed out before sending a file
import selectors
import sys
from socket import *
import sock
sel1 = selectors.DefaultSelector()
print(len(sys.argv), sys.argv[1], sys.argv[2], sys.argv[3])
host = sys.argv[1]
port = int(sys.argv[2])
file = sys.argv[3]
try:
# Instaniating socket object
s = socket(AF_INET, SOCK_STREAM)
# Getting ip_address through host name
host_address = gethostbyname(host)
# Connecting through host's ip address and port number using socket object
s.connect((host_address, port))
sel1.register(
sock,
selectors.EVENT_READ, data = None)
fileToSend = open("file.txt", "rb")
data = fileToSend.read(1024)
while data:
print("Sending...")
fileToSend.close()
s.send(b"Done")
print("Done Sending")
print(s.recv(1024))
s.shutdown(2)
s.close()
except:
# Returning False in case of an exception
sys.stderr.write("Connection Failed")
Do the writing in a loop. There's no particular reason to chop it into 1024-byte pieces; the network stack will handle that for you.
By the way, your "Done" signal is not a good idea, especially since you're writing a binary file that might very well contain the word "Done". Remember that TCP is a streaming protocol. The other end does not see the exact packets you're sending. That is, just because you send 1024 bytes and 4 bytes, the other end might see it as reads of 256 and 772 bytes.
# Instaniating socket object
s = socket(AF_INET, SOCK_STREAM)
# Getting ip_address through host name
host_address = gethostbyname(host)
# Connecting through host's ip address and port number using socket object
s.connect((host_address, port))
fileToSend = open("file.txt", "rb")
print("Sending...")
while True:
data = fileToSend.read(1024)
if not data:
break
s.send( data )
fileToSend.close()
s.send(b"Done")
print("Done Sending")
print(s.recv(1024))
s.close()

Unable to split a tuple object in Python: 'tuple' object has no attribute 'split'

When I try to run my program I get the error shown below:
Traceback (most recent call last):
File "/Volumes/USER/server.py", line 15, in <module>
filename = message.split()[1]
AttributeError: 'tuple' object has no attribute 'split'
I tried changing the value for
filename = message.split()[0] but it didn't work.
#import socket module
import socket
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#Prepare a sever socket
serverName = socket.gethostname()
serverPort = 1234
serverSocket.bind(('', serverPort))
serverSocket.listen(1)
while True:
#Establish the connection
print('Ready to serve...')
connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recvfrom(1024)
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.read()
#Send one HTTP header line into socket
header = 'HTTP/1.1 200 OK\r\n' +\
'Connection: close\r\n' + \
'Content-Type: text/html\r\n' + \
'Content-Length: %d\r\n\r\n' % (len(outputdata))
connectionSocket.send(header.encode())
#Send the content of the requested file to the client
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i].encode())
connectionSocket.close()
except IOError:
#Send response message for file not found
header = 'HTTP/1.1 404 Not Found\r\n\r\n'
connectionSocket.send(header.encode())
#Close client socket
connectionSocket.close()
serverSocket.close()
In the same directory as the program, server.py, I have a file called helloworld.html thats supposed to load when I go to the IP address of the server with the hard coded port and also show a 404 when I go to a file that doesn't exist. ex (192.168.1.2:1234/helloworld.html)
Per the documentation:
socket.accept()
Accept a connection. The socket must be bound to an address and listening for connections. The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection.
So, in your code, after you do
message = connectionSocket.recvfrom(1024)
filename = message.split()
message becomes a tuple (conn, address).
Now, tuples don't have the method split(). Only strings have that method. What I think you're trying to do is split the address - so you have to first get the second element of the tuple (which is, of course, a string), and then split that:
filename = message[1].split()

Error with python socket programming, winerror10057

This is my python code:
class SimpleWebServer():
def __init__(self, port):
threading.Thread.__init__(self)
self.port = port
self.BUFFER_SIZE = 8192
#Create a server socket
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)#YOUR CODE
try:
#Bind to a port
#YOUR CODE; 1 line
self.server.bind(('localhost', self.port))
except socket.error:
print('Bind failed %s' % (socket.error))
sys.exit()
#Listen to the server socket
#YOUR CODE; 1 line
self.server.listen(5)
def run_thread(self, conn, addr):
# connection timeout after 60-second inactivity
conn.settimeout(60.0)
print('Client connected with ' + addr[0] + ':' + str(addr[1]))
while True:
try:
# Receives the request message from the client
message = self.server.recv(1024)
# .decode("utf-8") #YOUR CODE
if not message: break
# Extract the path of the requested object from the message
# The path is the second part of HTTP header, identified by [1]
filename = message.split()[1].decode()
print('Client request ' + filename)
# Extract the file extention to determine file type
filename_extension = os.path.splitext(filename)[1]
# Open the local file f specified in filename for reading
# Because the extracted path of the HTTP request includes
# a character '\', we read the path from the second character
f = open(filename)#YOUR CODE
# Store the entire content of the requested file in a temporary buffer
msg = f #YOUR CODE
# Send the HTTP response headers to the connection socket
# 1. HTTP version and status code
# YOUR CODE 1-line
#conn.send_response(200, addr)
conn.sendall(bytearray("HTTP/1.1 200 OK"))
# 2. Keep-Alive field
# YOUR CODE 1-line
#conn.send_head("Timeout = 5", "Max - 30", addr)
conn.sendall(bytearray("Timeout = 5", "Max - 30"))
# 3. Content length field
# YOUR CODE 1 - 3 lines
#conn.send_header("Content-length", len(msg), addr)
conn.sendall(bytearray("Content-length", len(msg)))
# 4. Content type field (based on the file type)
# YOUR CODE
#conn.send_header("Content-type", "text/html", addr)
#conn.end_headers()
conn.sendall(bytearray("Content-type", "text/html"))
# Send the HTTP response body
for i in range(0, len(msg), self.BUFFER_SIZE):
end = min(i + self.BUFFER_SIZE, len(msg))
conn.send(msg[i: end])
# Exception handling
except FileNotFoundError:
# Send HTTP response message for file not found
# YOUR CODE 1 - 3 lines
self.send_response(404)
except socket.timeout:
#Socket timeout
print("Conn socket timeout!")
break
except socket.error as e:
#Other socket exceptions
print("Socket error: %s" % e)
break
conn.close() # Close socket
def run(self):
print('Waiting for connections on port %s' % (self.port))
while True:
#Accept a new connection
try:
#Waiting for connection request
(conn, addr) = self.server.accept()
#Start a new thread to handle HTTP request/response
threading.Thread(target=self.run_thread, args=(conn, addr)).start()
except:
break
# Close the server socket
self.exit()
def exit(self):
"""Close server socket"""
self.server.close()
I call the class here:
if __name__ == '__main__':
parser = optparse.OptionParser(usage="%prog ServerPort")
options, args = parser.parse_args()
if len(args) < 1:
parser.error("No ServerPort")
else:
if validate_port(args[0]):
server_port = int(args[0])
else:
parser.error("ServerPort invalid!")
#Create and start the server
server = SimpleWebServer(server_port)
server.run()
I call the script via powershell and I get this error:
Client connected with 127.0.0.1:2654
Socket error: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
I'm running this command in my browser to try and access this socket:
http://localhost:8888/index.html
I have no clue what I should be doing to fix this. There is a lot of documentation for python socket programming and I've tried many of the different methods but nothing has worked so far.

Cache Proxy Server in Python

I have a homework assignment which involves implementing a proxy cache server in Python. The idea is to write the web pages I access to temporary files on my local machine and then access them as requests come in if they are stored. Right now the code looks like this:
from socket import *
import sys
def main():
#Create a server socket, bind it to a port and start listening
tcpSerSock = socket(AF_INET, SOCK_STREAM) #Initializing socket
tcpSerSock.bind(("", 8030)) #Binding socket to port
tcpSerSock.listen(5) #Listening for page requests
while True:
#Start receiving data from the client
print 'Ready to serve...'
tcpCliSock, addr = tcpSerSock.accept()
print 'Received a connection from:', addr
message = tcpCliSock.recv(1024)
print message
#Extract the filename from the given message
print message.split()[1]
filename = message.split()[1].partition("/")[2]
print filename
fileExist = "false"
filetouse = "/" + filename
print filetouse
try: #Check whether the file exists in the cache
f = open(filetouse[1:], "r")
outputdata = f.readlines()
fileExist = "true"
#ProxyServer finds a cache hit and generates a response message
tcpCliSock.send("HTTP/1.0 200 OK\r\n")
tcpCliSock.send("Content-Type:text/html\r\n")
for data in outputdata:
tcpCliSock.send(data)
print 'Read from cache'
except IOError: #Error handling for file not found in cache
if fileExist == "false":
c = socket(AF_INET, SOCK_STREAM) #Create a socket on the proxyserver
hostn = filename.replace("www.","",1)
print hostn
try:
c.connect((hostn, 80)) #https://docs.python.org/2/library/socket.html
# Create a temporary file on this socket and ask port 80 for
# the file requested by the client
fileobj = c.makefile('r', 0)
fileobj.write("GET " + "http://" + filename + "HTTP/1.0\r\n")
# Read the response into buffer
buffr = fileobj.readlines()
# Create a new file in the cache for the requested file.
# Also send the response in the buffer to client socket and the
# corresponding file in the cache
tmpFile = open(filename,"wb")
for data in buffr:
tmpFile.write(data)
tcpCliSock.send(data)
except:
print "Illegal request"
else: #File not found
print "404: File Not Found"
tcpCliSock.close() #Close the client and the server sockets
main()
To test my code, I run the proxy cache on my localhost and set my browser proxy settings accordingly like so
However, when I run this code and try to access google with Chrome, I'm greeting with an error page saying err_empty_response.
Stepping through the code with the debugger made me realizing it's failing on this line
c.connect((hostn, 80))
and I have no idea why. Any help would be greatly appreciated.
P.S. I'm testing this with Google Chrome, Python 2.7, and Windows 10
You cannot use a name on connect. Connect expects an IP address to connect to.
You can get the socket information you need to build the connection using getaddrinfo(). In my pure-python-whois package I used the following code to create a connection:
def _openconn(self, server, timeout, port=None):
port = port if port else 'nicname'
try:
for srv in socket.getaddrinfo(server, port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_ADDRCONFIG):
af, socktype, proto, _, sa = srv
try:
c = socket.socket(af, socktype, proto)
except socket.error:
c = None
continue
try:
if self.source_addr:
c.bind(self.source_addr)
c.settimeout(timeout)
c.connect(sa)
except socket.error:
c.close()
c = None
continue
break
except socket.gaierror:
return False
return c
Note that this isn't great code because the loop is actually there for nothing instead of using the different alternatives. You should only break the loop once you have established a connection. However, this should work as an illustration for using getaddrinfo()
EDIT:
You are also not cleaning your hostname correctly. I get /www.example.com/ when I try accessing http://www.example.com/ which obviously won't resolve. I'd suggest that you use a regular expression to get the file name for your cache.

How do I get the "except" to trigger?

We're learning about sockets in Networking and we've been tasked to fill out a template in Python (teacher's using Python2.x while I'm using Python3.x).
# Import socket module
from socket import *
# Create a TCP server socket
#(AF_INET is used for IPv4 protocols)
#(SOCK_STREAM is used for TCP)
serverSocket = socket(AF_INET, SOCK_STREAM)
# Assign a port number
serverPort = 6789
# Bind the socket to server address and server port
serverSocket.bind(('',serverPort))
# Listen to at most 1 connection at a time
serverSocket.listen(1)
# Server should be up and running and listening to the incoming connections
while True:
print ("Ready to serve...")
# Set up a new connection from the client
connectionSocket, addr = serverSocket.accept()
# If an exception occurs during the execution of try clause
# the rest of the clause is skipped
# If the exception type matches the word after except
# the except clause is executed
try:
# Receive the request message from the client
message = connectionSocket.recv(4096).decode()
# Extract the path of the requested object from the message
# The path is the second part of HTTP header, identified by [1]
filename = message.split()[1]
# Because the extracted path of the HTTP request includes
# a character '\', we read the path from the second character
f = open(filename[1:])
# Store the entire contenet of the requested file in a temporary buffer
outputdata = f.read()
# Send the HTTP response header line to the connection socket
connectionSocket.send(("HTTP/1.1 200 OK \r\n").encode())
# Send the content of the requested file to the connection socket
for i in range(0, len(outputdata.encode())):
connectionSocket.send(outputdata.encode())
connectionSocket.send(("\r\n").encode())
# Close the client connection socket
connectionSocket.close()
break
except IOError:
# Send HTTP response message for file not found
connectionSocket.send(("HTTP/1.1 404 NOT FOUND\r\n").encode())
connectionSocket.send(("<html><head></head><body><h1>ERROR. TRY AGAIN</h1></body></html>\r\n").encode())
# Close the client connection socket
connectionSocket.close()
break
#Close the Socket
serverSocket.close()
The file I'm reading into it is a .htm file:
<html><head><title>HTML Test File</title></head><body><h1>Trying to Get This Frickin' Program to Work</h1></body></html>
When I run the program and enter: localhost:6789/TestFile.htm, it prints the file contents over and over and gives me the error message: line 34, indexerror: list index out of range. edit: break takes care of the error message, but file is still being printed over and over
What am I doing wrong?
edit #2: now I'm trying to do the error handling, but it merely states that no data was sent when I type in a file that doesn't exist (i.e. localhost:6789/Test.htm). How do I get the error message to print?
for i in range(0, len(outputdata.encode())):
connectionSocket.send(outputdata.encode())
This code:
encodes the text twice
loops 121 times (which is the length of the file you posted, encoded as ASCII or UTF-8)
sends the entire file each of the 121 times

Categories