Python not sending all data, only 4kb - python

I am attempting to create a Python web server however it seems to not be able to send any files larger then 4KB. If the file is above 4KB in size it just cuts off the end of the text/image past 4KB. Anything embedded from other sources (Amazon S3/Twitter) work fine.
Here is the server code. It is a bit of a mess at the moment but I am focused on getting it to work. Afterwards I will add more security to the code.
'''
Simple socket server using threads
'''
import socket
import sys
import time
import os
from thread import *
HOST = '' # Symbolic name meaning all available interfaces
PORT = 80 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
#Bind socket to local host and port
try:
s.bind((HOST, PORT))
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(10)
print 'Socket now listening'
#Function for handling connections. This will be used to create threads
def clientthread(conn):
#Sending message to connected client
#infinite loop so that function do not terminate and thread do not end.
while True:
#Receiving from client
data = conn.recv(4096)
print data
dataSplit = data.split(' ')
print dataSplit
contentType = "text/html"
if(dataSplit[1].endswith(".html")):
print "HTML FILE DETECTED"
contentType = "text/html"
elif(dataSplit[1].endswith(".png")):
print "PNG FILE DETECTED"
contentType = "image/png"
elif(dataSplit[1].endswith(".css")):
print "CSS FILE DETECTED"
contentType = "text/css"
else:
print "NO MIMETYPE DEFINED"
conn.sendall('HTTP/1.1 200 OK\nServer: TestWebServ/0.0.1\nContent-Length: ' + str(os.path.getsize('index.html')) + '\nConnection: close\nContent-Type:' + contentType + '\n\n')
print '\n\n\n\n\n\n\n\n'
with open(dataSplit[1][1:]) as f:
fileText = f.read()
n = 1000
fileSplitToSend = [fileText[i:i+n] for i in range(0, len(fileText), n)]
for lineToSend in fileSplitToSend:
conn.sendall(lineToSend)
break
if not data:
break
#came out of loop
conn.close()
#now keep talking with the client
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
#start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.
start_new_thread(clientthread ,(conn,))
s.close
Thank you for your time.

So, thanks you the user "YOU" we found the problem. I had this code:
conn.sendall('HTTP/1.1 200 OK\nServer: TestWebServ/0.0.1\nContent-Length: ' + str(os.path.getsize('index.html')) + '\nConnection: close\nContent-Type:' + contentType + '\n\n')
instead of this code:
conn.sendall('HTTP/1.1 200 OK\nServer: TestWebServ/0.0.1\nContent-Length: ' + str(os.path.getsize(dataSplit[1][1:])) + '\nConnection: close\nContent-Type:' + contentType + '\n\n')
The problem was that I was sending the file size for index.html for every file, so Chrome and other browsers just removed the extra data. It just so happened index.html was 4KB so I though it was a packet limitation or something in that area.

Related

Creating a chat room - got an error [WinError 10038] An operation was attempted on something that is not a socket

I created a server/client code to create a chat room using socket programming and multi-threading.I encountered an error that i dont seem to understand The server code is working, but i am facing issues with the client code and idk why it is saying its not a socket. i would appreciate any help on this.
Server code
import socket
import sys
from _thread import *
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# checks whether sufficient arguments have been provided
# if len(sys.argv) != 3:
# print ("missing arguments enter: <IP address> <port number>")
# exit()
# first argument from command prompt is IP address
IP_address = '127.0.0.1'
# second argument from command prompt is port number
Port = 12000
# binds the server to an entered IP address and specified port number.
server.bind((IP_address, Port))
# listens for 10 active connections
server.listen(10)
list_of_clients = []
def clientthread(conn, addr):
# sends a message to the client whose user object is conn
conn.send("Welcome to Network Programming chatroom!")
# broadcast to other that a new client has joined
message_to_send = "<" + addr[0] +", " + str(addr[1]) + "> joined"
broadcast(message_to_send, conn)
while True:
try:
message = conn.recv(4096)
if message:
# prints the message and address of the user who just sent the message
print ("<" + addr[0] + ", " + str(addr[1]) + ">: " + message)
# call broadcast function to send message to all other clients
message_to_send = "<" + addr[0] +", " + str(addr[1]) + ">: " + message
broadcast(message_to_send, conn)
else:
''' message have no content if the connection is broken, then
send message to others and remove the connection'''
print("connection : <" + addr[0] + ", " + str(addr[1]) + "> disconnected")
message_to_send = "<" + addr[0] +", " + str(addr[1]) + "> left"
broadcast(message_to_send, conn)
remove(conn)
break
except:
print("error occurred and ignored with: <" + addr[0] +", " + str(addr[1]) + "> connection")
continue
""" broadcast function is used to broadcast a message to all
clients (but not the sender) """
def broadcast(message, connection):
for client in list_of_clients:
if client != connection:
try:
client.send(message)
except:
client.close()
# if the link is broken, remove the client
remove(client)
''' remove function to remove the object from the list of clients '''
def remove(connection):
if connection in list_of_clients:
list_of_clients.remove(connection)
print("Welcome to Network Programming chatroom!\nServer is waiting for clients...")
while True:
""" accepts a connection request and stores two parameters:
conn socket object and addr of the connected client"""
conn, addr = server.accept()
""" maintains a list to keep track of all available clients in the chatroom"""
list_of_clients.append(conn)
# prints the address of the user that just connected
print (addr[0], addr[1], " joined")
# creates an individual thread for every client
start_new_thread(clientthread,(conn,addr))
conn.close()
server.close()
Client code
import socket
import select
import sys
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# if len(sys.argv) != 3:
# print ("missing arguments enter: <IP address> <port number>")
# exit()
IP_address = '127.0.0.1'
Port = 12000
server.connect((IP_address, Port))
while True:
# create a list to maintain possible input streams
sockets_list = [sys.stdin, server]
""" Two possible inputs scenarios. Either the
user enters text to send to other clients, or the
server is sending a message to the client. """
""" select system call returns from sockets_list, the stream
that is reader for input. So for example, if the server sent a message, then the if condition will hold true below.
If the user wants to send a message, the else
condition will evaluate as true"""
print("wait on select call...")
read_sockets, write_sockets, error_sockets = select.select(sockets_list,[],[])
print("select call returned")
print("read_sockets: ", read_sockets)
#print("write_sockets: ", write_sockets)
#print("error_sockets: ", error_sockets)
for socks in read_sockets:
if socks == server:
message = socks.recv(4096)
if(len(message) != 0):
print(message)
# server sent empty message, print error and leave
else:
print("Server is down, join later once it is up!")
exit()
else:
message = sys.stdin.readline()
server.send(message)
sys.stdout.write("<You>")
sys.stdout.write(message)
sys.stdout.flush()
server.close()
Output on client
Traceback (most recent call last):
File "C:/Users/a/Desktop/Network Programming 2/chat-client.py", line 23, in <module>
read_sockets, write_sockets, error_sockets = select.select(sockets_list,[],[])
OSError: [WinError 10038] An operation was attempted on something that is not a socket
wait on select call...
You put sys.stdin on your sockets_list. It is, as the error says, not a socket. On Unix that would be okay, but on Windows you can't do it.

How to effectively multi-thread functions based on data received from a socket in python?

Here is a snippet from a specific server program I a working on.
Requirements:
I want the program to initiate a socket on port defined by ownport variable and listen on that port for incoming TCP messages.
Based on the specific value I receive on the socket from remote hosts, the server has to initiate functions func1() or func2() [Example: if the value is JOIN, then execute func1 and if it is UPDATE execute func2]
These actions are mutually exclusive and multiple clients may be connected to the server at the same time and might be sending requests.
How can I effectively multithread this so that the server constantly listen on the port and initiate the functions based on the incoming requests in realtime?
# Creating a socket
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
sys.exit();
print "Socket created!"
#Binding the socket to specified ports
try:
sock.bind((ownhost, ownport))
except socket.error , msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket bind complete'
# Listening for incoming requests
sock.listen(10)
print 'Socket now listening'
conn, addr = sock.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
# Handling the incoming requests received
req = conn.recv(1024)
reqpro = req.split('|')
# If the request is a join request
if reqpro[0] == "JOIN":
func1(reqpro, arg2)
elif (reqpro[0] == 'UPDATE') and (reqpro[1] == 'PRED'):
func2(reqpro,arg2)
else:
print "invalid request type"
sys.exit()

Very basic Python web server - strange issue

I'm just starting out with Python and I'm trying to code a simple web server. Everything seems to be work except I'm having one small problem. When I request a specific file like Test.html from my web server, the data in the HTML file is repeated over and over in my client like its stuck in a loop. So instead of seeing just "Test" displayed in the web client once, I see "Test Test Test Test Test Test...many times over". This is probably a simple error but I was hoping someone could point me in the right direction.
Thanks for you help!
import socket
import sys
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket Created!!")
try:
#bind the socket
#fill in start
server_address = ('localhost', 6789)
serversocket.bind(server_address)
#fill in end
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 the socket
#fill in start
serversocket.listen(1)
#fill in end
print('Socket now listening')
while True:
#Establish the connection
connectionSocket, addr = serversocket.accept()
print('source address:' + str(addr))
try:
#Receive message from the socket
message = connectionSocket.recv(1024)
print('message = ' + str(message))
#obtian the file name carried by the HTTP request message
filename = message.split()[1]
print('filename = ' + str(filename))
f = open(filename[1:], 'rb')
outputdata = f.read()
#Send the HTTP response header line to the socket
#fill in start
connectionSocket.send(bytes('HTTP/1.1 200 OK\r\n\r\n','UTF-
8'))
#fill in end
#Send the content of the requested file to the client
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata)
#close the connectionSocket
#fill in start
connectionSocket.close()
#fill in end
print("Connection closed!")
except IOError:
#Send response message for file not found
connectionSocket.send(bytes("HTTP/1.1 404 Not
Found\r\n\r\n","UTF-8"))
connectionSocket.send(bytes("<html><head></head><body><h1>404
Not Found</h1></body></html>\r\n","UTF-8"))
#Close the client socket
#fill in start
connectionSocket.close()
serverSocket.close()
You are stuck in a loop :)
#fill in end
#Send the content of the requested file to the client
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata)
You're sending the contents of outputdata the number of times however long the length of the file is.
You only need connectionSocket.send(outputdata) without the for..loop to send it once.
Also, make sure you close the file you read the contents from. (f.close())

Python - Socket Communication, multiple messages

I'm stuck on this socket communication, I've looked everywhere but I haven't found an answer yet.
THE PROBLEM: I can only send 1 message from the client before it either gives me an error or ends the script.
I need to be able to send multiple messages to the server.
The server side (shown below) should be fine:
# Echo server program
import socket
import time
import os
#-----------------------------------------------------------------------------------------------------------------------
today = time.strftime('%Y.%m.%d')
logFileName = "log - " + today + ".txt"
HOST = '10.0.0.16'
PORT = 8080 # Reserve a port for your service
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Create a socket object
s.bind((HOST, PORT)) # Bind to the port
def print_write(text):
log.write(time.strftime("%H:%M:%S") + " | " + text)
log.write("\n")
print text
#-----------------------------------------------------------------------------------------------------------------------
if os.path.isfile(logFileName) is True:
log = open(logFileName, 'a+')
print_write("[SERVER] Log for " + today + " already exists.")
print_write("[SERVER] Starting comms")
else:
print "[SERVER] Log doesn't exist"
log = open(logFileName, 'a+') # Create file -> log - %date%.txt
print_write("[SERVER] Log created")
while True:
s.listen(1)
conn, addr = s.accept()
data = conn.recv(BUFFER_SIZE)
if data == "Comms Shutdown":
print_write("------ REMOTE SHUTDOWN ------")
conn.close()
raise SystemExit
else:
print_write("[COMMS] " + str(addr) + " says: " + data)
log.close()
Sorry if it's very messy and confusing but i don't have much time to finish this project, if you have any question just ask.
For the client side I don't have much but here, I'll give you this:
import socket
HOST = '10.0.0.16' # The remote host
PORT = 8080 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
msg = raw_input()
s.sendall(msg)
print msg
I know it doesn't work, it's just to give you an idea of what I need.
Thank you in advance.
The problem is, that you only read the first message from each open connection before moving on to the next. The accept() methods waits for a new connection and gives you the information needed when a new one comes in. the recv() method on the other hand, receives data from a existing connection and waits if there is none. If you want to receive multiple messages from a single client, you can just wait for the first connection and then wait for data with recv(). This could look like this:
s.listen(1)
conn, addr = s.accept()
while True:
data = conn.recv(BUFFER_SIZE)
if data == "Comms Shutdown":
print_write("------ REMOTE SHUTDOWN ------")
conn.close()
raise SystemExit
else:
print_write("[COMMS] " + str(addr) + " says: " + data)
If you want to be able to also manage multiple clients, you will have to create a thread for each one from a while loop waiting for new connections. This is a bit more complicated:
def client_handler(conn):
while True:
data = conn.recv(BUFFER_SIZE)
if data == "Comms Shutdown":
print_write("------ REMOTE SHUTDOWN ------")
conn.close()
raise SystemExit
# this will kill the server (remove the line above if you don't want that)
else:
print_write("[COMMS] " + str(addr) + " says: " + data)
while True:
s.listen(1)
conn, addr = s.accept()
recv_thread = threading.Thread(target=client_handler, args=(conn, ))
recv_thread.start()
All this code is untested. Be aware, that I omitted the logging part and the socket creation part as well as all imports.

Where is the right place to close a server socket (Python)

I have a server program that can maintain connection with multiple clients. I want to be able to close the socket in response to the message CLOSE by client, or for some other reason. The problem is that the server is stuck on the accept() method and does not care if I close the socket in some other place.
I can use some flag in the main server while, and close the socket after this while, however that means I will have to connect to the server myself after the client request, in order for the while condition to be checked, which smells like really terrible programming.
The code:
import socket
import sys
from thread import *
HOST = '' # Symbolic name meaning all available interfaces
PORT = 9992 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
#Bind socket to local host and port
try:
s.bind((HOST, PORT))
except socket.error , msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket bind complete'
#Start listening on socket
s.listen(10)
print 'Socket now listening'
#Function for handling connections. This will be used to create threads
def clientthread(conn):
#Sending message to connected client
conn.send('Welcome to the server. Type something and hit enter\r\n') #send only takes string
data=''
#infinite loop so that function do not terminate and thread do not end.
while True:
#Receiving from client
data += conn.recv(1024)
print data
if data == 'CLOSE':
global s
conn.sendall('You have requested to destroy the connection...')
conn.close()
s.close()
return
if data.find('\n') != -1:
conn.sendall('OK...' + data + '\r\n')
data=''
#now keep talking with the client
while 1:
#wait to accept a connection - blocking call
try:
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
#start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.
start_new_thread(clientthread ,(conn,))
except:
print 'socket issue sorry'
break

Categories

Resources