Im coding a chat program with python. But when i write "host = socket.gethostname()" it gives me error. My file is named "server.py" (without quotes) How can i fix? Code:
import socket
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostbyname()
port = 12347
socket.bind((host, port))
socket.listen(10)
c, addr = socket.accept()
c.sendall(bytes("Hi!".encode("utf-8")))
print("Connected to {}".format(addr))
while True:
data = str(c.recv(1024))[1:]
if data:
print("Client: {}".format(data))
respond = input("Server: ").encode("utf-8")
if respond == "q":
exit()
else:
c.sendall(bytes(respond.encode("utf-8")))
this should be a red flag:
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
when importing socket, socket is the socket module. The line above assigns the name socket to a socket object.
Then
host = socket.gethostbyname()
doesn't work because the method applies to the module, but the module name has been reassigned to the socket object.
That would work (renaming your socket object):
import socket
my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostbyname("localhost") # needs an argument, btw
Related
I'm just very confused still about the basic socket process. Tried multiple ways to try and get the socket to connect but it keeps refusing.
client code- socket_client.py
import socket
host = socket.gethostname()
port = 8080
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host,port))
res = client.send (b' testing data send...')
client.close()
server code- server_client.py
import socket
host = socket.gethostname()
port = 8080
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen(10)
x=0
server_data = []
while True:
conn, addr = server.accept()
data = conn.recv(4096).decode()
x += 1
print ('Servicing client at %s'%addr[0])
server_data = client.recv(4096)
client_close()
server.close()
You have some problems in your server. You read from the connection but never use it, and you do client.recv when there is no variable client. This works:
import socket
host = socket.gethostname()
port = 8080
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen(10)
x=0
server_data = []
while True:
conn, addr = server.accept()
x += 1
print ('Servicing client at %s'%addr[0])
data = conn.recv(4096).decode()
print( "Received", data )
conn.close()
server.close()
Do remember that Python has a SocketServer module that can make some of this easier. If you need to get fancier, there are few modules better than Twisted at this kind of thing.
ALSO remember that the server must be running before you start the client. Someone has to be listening, otherwise the connection is rejected.
I know that similar questions have been raised but they don't seem to work for me! I have tried serializing the dictionary then converting that to a string then encoding it before I send it over the socket. No success so far!
This is my server code:
#library
import socket
import pickle
#socket initialization
host = "127.0.0.1"
port = 5000
mainAddr = (host, port)
#dict initialization
dataDict = {} #just imagine that dict has content
#create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP
s.bind((mainAddr))
s.listen(4)
print('program started')
print('listening..')
while True:
try:
conn, addr = s.accept()
print("connection from: "+str(addr))
print("sending message..")
pickle.dumps(dataDict)
print('pickled!')
dataS = str(dataP)
print('stringed!')
dataE = dataS.encode('UTF-8')
print('encoded!')
s.sendto(dataE,addr)
print('data sent!')
except:
pass
s.close()
For the socket initialization, I've tried other types:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #UDP
s = socket.socket()
For the sending part, I've tried these alternatives:
s.send(dataE)
s.send(dataE,addr)
s.sendall(dataE)
s.sendall(dataE,addr)
When I run the program, these get printed out:
program started
listening..
connection from:<insert addr here>
sending message..
pickled!
stringed!
encoded!
Only data sent! is not sent. So I am guessing that it's the sending part that has a problem.
For the client side, here's the code:
#library
import socket
import pickle
#initialization
host = '127.0.0.1'
port = 5000
buffer = 1024
#create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP
s.connect((host,port))
print('connected!')
#receive dictionary
print('receiving message..')
while True:
data, addr = s.recvfrom(buffer)
print('received!')
dataD = data.decode("UTF-8")
print('decoded!')
dataP = pickle.loads(dataD)
print('unpickled!')
print(str(dataP))
s.close()
In the client terminal, only the following prints:
connected!
receiving message..
On the client side, I've tried changing the order of unpickling and decoding but still, to no avail.
A TCP server socket is not actually used for sending/receiving data; I'm surprised you're not getting an error when calling s.send() or similar on it. Instead, it's a factory for producing individual sockets for each client that connects to the server - conn, in your code. So, conn.sendall() is what you should be using. No address parameter is required, the individual socket already knows who it is talking to. (.send() is unreliable without some extra work on your part; .sendto() is only used with UDP sockets that have not been connected to a particular client.)
#!/usr/bin/env python
import socket
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('192.168.1.123', 5162))
clientsocket.send('getval.1')
clientsocket.close
clientsocket.bind(('192.168.1.124', 5163))
clientsocket.listen(1)
while True:
connection, address=clientsocket.accept()
value=connection.recv(1024)
print value
I'm trying to get python to send a message to the server, and in return the server responds. Yet when I execute this code it gives me
Socket.error: [Errno 10022] An invalid argument was supplied
It seems you wrote a mixed code of server and client
Here a simple sample of codes for socket programming the first on server side and the second on client
Server side code:
# server.py
import socket
import time
# create a socket object
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = socket.gethostname()
port = 9999
# bind to the port
serversocket.bind((host, port))
# queue up to 5 requests
serversocket.listen(5)
while True:
# establish a connection
clientsocket,addr = serversocket.accept()
print("Got a connection from %s" % str(addr))
currentTime = time.ctime(time.time()) + "\r\n"
clientsocket.send(currentTime.encode('ascii'))
clientsocket.close()
and now the client
# client.py
import socket
# create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = socket.gethostname()
port = 9999
# connection to hostname on the port.
s.connect((host, port))
# Receive no more than 1024 bytes
tm = s.recv(1024)
s.close()
print("The time got from the server is %s" % tm.decode('ascii'))
The server simply remained listened for any client and when it finds out a new connection it returns current datetime and closes the client connection
I'm trying the following client and server chat program. Although I get an error whenever I try to run the server program, when the client program runs it stays on a blank screen not allowing me to type anything. I've tried running server first and running client first and I get the same results. I can't read the error from the server program because it flashes the error and closes the window. Here is my code:
server:
#server
import socket
import time
HOST = ''
PORT = 8065
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((HOST,PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
conn.close()
client:
#client
import socket
import time
HOST = "localhost"
PORT = 8065
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect((HOST,PORT))
s.sendall('Helloworld')
data = s.recv(1024)
s.close()
print 'Recieved', repr(data)
Im not an expert but I was able to make your examples work by changing the socket from datagram to stream connection, and then encoding message being sent because strings aren't supported (although this might not effect you since I think that change was made in Python 3...I'm not 100% sure).
I believe the main issue is that you're trying to listen() but SOCK_DGRAM (UDP) doesn't support listen(), you just bind and go from there, whereas SOCK_STREAM (TCP) uses connections.
If you're just trying to get the program going, use the below code, unless there is a specific reason you'd like to use SOCK_DGRAM.
The code is below:
client
#client
import socket
import time
HOST = "localhost"
PORT = 8065
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
test = 'Helloworld'
s.sendall(test.encode())
data = s.recv(1024)
s.close()
print 'Recieved', repr(data)
server
#server
import socket
import time
HOST = ''
PORT = 8065
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST,PORT))
s.listen(1)
conn, addr = s.accept()
print ('Connected by', addr)
while 1:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
conn.close()
I have a server written in python 2.7 that executes an infinite loop and process information from port 5000. Is it possible to change this connection port without restarting the server?
For example: the server is running in port 5000 and receives a 'change_port' option, the server module has to stop listening in port 5000 to start listening in port 7000. I don't know if i can manipulate sockets like that... Thanks
Once you have bound a socket to an address (interface, port) it cannot be changed. However, you can create a new socket (or many, depending on your needs) and bind it to your address (interface, port).
The code will differ based on the transport layer protocol you're using:
TCP:
# 1) Create first socket
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind(('0.0.0.0',5000))
# 2) Create second socket
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.bind(('0.0.0.0',7000))
# 3) Wait for a connection on the first socket
s1.listen(5)
sc, address = s1.accept()
# 4) Once a connection has been established...
# send, recv, process data
# until you need the next socket
# 5) Open connection on second socket
s2.listen(1)
sc2, address2 = s2.accept()
# now it probably a good time to tell the client (via s1) that s2 is ready
# client connects to s2
There you go
UDP (almost the same):
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.bind(('0.0.0.0',5000))
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2.bind(('0.0.0.0',7000))
data, addr = s1.recvfrom(256)
s1.sendto("s2 ready",addr)
data2, addr2 = s2.recvfrom(256)
Simplified, but that's all there really is to it.
You might consider verifying that the address of the client from s1 is the same as the client connecting to s2.
No, it seems that you cannot run the socket.bind() method when its already bound. However, I have a solution you can use with the Asyncore module.
Heres my server:
import asyncore
import socket
class EchoHandler(asyncore.dispatcher_with_send):
def handle_read(self):
data = self.recv(8192)
if data:
print "Recieved Data: ", data, ". This server address:", self.getsockname()
class EchoServer(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((host, port))
self.listen(5)
def handle_accept(self):
pair = self.accept()
if pair is not None:
sock, addr = pair
print 'Incoming connection from %s' % repr(addr)
handler = EchoHandler(sock)
server = EchoServer('localhost', 56787)
server = EchoServer('localhost', 56788)
asyncore.loop()
Here are my clients:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 56787))
data = ""
while data.upper() != "Q":
data = raw_input("Enter something to send to the server")
s.send(data)
s.close()
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 56788))
data = ""
while data.upper() != "Q":
data = raw_input("Enter something to send to the server")
s.send(data)
s.close()
This worked well, the python handled both ports. You should also be able to define seperate server classes for each of your ports.