Python3 socket doesn't work - graphite - python-3.x

I created a function to send data to a graphite server. It sends the metricname, value and the timestamp to the graphite server at execution:
def collect_metric(metricname, value, timestamp):
sock = socket.socket()
sock.connect( ("localhost", 2003) )
sock.send("%s %s %s\n" % (metricname, value, timestamp))
sock.close()
This function above worked fine in Python2. I had to rewrite this function for Python3. Now no data will be send to graphite. No log entries in the graphite/carbon logs or something else ...:
def collect_metric(metricname, value, timestamp):
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect( ("localhost", 2003) )
metricname = metricname.encode()
if type(value) == "str":
value = value.encode()
timestamp = timestamp.encode()
message = bytearray()
message = bytes(metricname+b" "+value+b" "+timestamp)
sock.sendall(message)
print(message.decode())
sock.close()
I receive no errors. Also on terminal I get the right format/output (see "print(message.decode())")
Has anybody some ideas why it doesn't work?
Thanks.

The bytearray is without any encoding. Try this:
message = (metricname+" "+value+" "+timestamp).encode("UTF-8")
sock.send(messages)

It seems like you're missing '\n' at the end of the message you're sending
message = bytes(metricname+b" "+value+b" "+timestamp)
should be:
message = bytes(metricname+b" "+value+b" "+timestamp + '\n')

Related

How to send integer through socket in python

Actually, I want to send integers through the server to client and vice versa. So that I can apply some operations on them on the client/server side. But whenever I a try to send integers, the server or client gets automatically destroyed even without sending the message. I have also used a while loop but it's not working as it was supposed to do?
Also, it works fine when I send strings (encoded)
--->server side<----
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print("--------------->SERVER<-----------------")
ip = "127.0.0.1"
port = 8080
s.bind((ip,port))
s.listen(2)
conn,addr = s.accept()
print("CONNECTED WITH THE CLIENT\n")
while True:
#for sending message
temp_msg = input("SERVER - ")
message = int(temp_msg.encode())
conn.send(message)
#for receiving message
rec_msg = conn.recv(1024)
print("CLIENT - ",rec_msg, " type = ", type(rec_msg))
---> client side <----
import socket
print("--------->CLIENT<----------------")
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = "127.0.0.1"
port = 8080
s.connect((ip,port))
print("CLIENT1 IS CONNECTED TO THE SERVER")
while True:
#for receiving message
rec_msg = s.recv(1024)
rec_msg = rec_msg
print("SERVER - ", rec_msg," type = ", type(rec_msg))
#for sending message
temp_msg = input("CLIENT - ")
message = int(temp_msg)
s.send(message)
----> output of client side code after sending the initial message through server.py<------
--------->CLIENT<----------------
CLIENT1 IS CONNECTED TO THE SERVER
SERVER - b'' type = <class 'bytes'>
CLIENT -
I found a very simple method to send integer by converting them to string before sending, and then change back to to the integer format after receiving them through a socket.
You can do this by following the below method.
#server side:
num=123
# convert num to str, then encode to utf8 byte
tcpsocket.send(str(num).encode('utf8'))
#client side
data = tcpsocket.recv(1024)
# decode to unicode string
strings = data.decode('utf8')
#get the num
num = int(strings)

how do i make my server able to read data which is sent by client

here i am making server
my_selector = selectors.DefaultSelector()
keep_running = True
server_address = ('localhost', 1040)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(False)
sock.bind(server_address)
sock.listen(5)
my_selector.register(sock, selectors.EVENT_READ, data=None)
this accept function make new connection
def accept(sock):
# print("Accept Function")
new_connection, addr = sock.accept()
print("Connection established.......")
new_connection.setblocking(False)
my_selector.register(new_connection, selectors.EVENT_READ | selectors.EVENT_WRITE, data=None)
this read function reads data sent by client
def read(connection, mask):
global keep_running
print("Read Function")
if mask & selectors.EVENT_READ:
recv_data = connection.recv(1024)
if recv_data:
print("Message received ", recv_data.decode("utf-8"))
else:
print("Message not received")
my_selector.unregister(connection)
connection.close()
keep_running = False
this loop controls my server
while keep_running:
for key, mask in my_selector.select(timeout=None):
if key.data is None:
accept(key.fileobj)
else:
read(key, mask)
my_selector.close()
my question is when server and client run if server gets a new client it control goes to accept function
or if server gets data it goes to read function this programme shows error
client programme does not show any error client programme only send data
please tell me how to fix this error and i am working on windows 10
Error----OSError: [WinError 10022] An invalid argument was supplied
Try looking at this post maybe it helps you :)
The first answer on that where the guy is having the same error says:
Bind the socket before calling connection.recvfrom(65536) using connection.bind((YOUR_IP, PORT)).
OSError: [WinError 10022] An invalid argument was supplied - Windows 10 Python

Python Can't decode byte : Invalid start byte

So I'm building this socket application, and it works just fine on my computer. But when i start server socket on another laptop, it just crashes with a invalid start byte error:
How do i proper encode the program to work with all laptops
This is the error i get on :
Other laptops.
My laptop.
I have tried to change the encoding, but I'm just not quite sure where i have to change it.
Class Listener:
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_address = (socket.gethostbyname(socket.gethostname()), 10000)
self.sock.bind(self.server_address)
print(f"LISTENER : {str(self.server_address[0])} port {str(self.server_address[1])}")
def listen(self):
self.sock.listen(1)
while True:
print("Connection Open")
print(" Waiting for connections")
self.connection, self.client_address = self.sock.accept()
try:
print(f"Connection from {str(self.client_address)}")
while True:
data = self.connection.recv(1024)
if data:
message = str(data)
if not "print" in message.lower(): # This just checks if the client wants to print system information from the server
Validate(message) # this checks for a command the server have to do
else:
self.connection.sendall(pickle.dumps(self.computerinfomation))
else:
self.listen()
except Exception as e:
print(e)
I want it to work on other laptops as well, and i just cant see why it wont.
Furas came with a solution.
I changed the
message = str(data)
to
message = str(data, encoding="utf-8")
I did the same on the client side
Not going to lie. I just changed the encoding = utf-16.
Example:
df = pd.read_csv(C:/folders path/untitled.csv, encoding = "utf-16")

Python36 and sockets

So I'm connected to an IRC chat using socket.connec
I log in by passing my variables via socket.send
The log in is successful and then I sit in a while true loop using
Socket.recv(1024)
If I just continually print the response everything looks fine, but let's say I want to add to the end of the string... I noticed that socket.recv doesn't always get the full message (only grabs up to 1024 as expected) and the remainder of the message is in the next iteration of the loop.
This makes its it impossible to process the feedback line by line.
Is there a better way to constantly read the data without it getting trunked? Is it possible to figure out the size of the response before receiving it so the buffer can be set dynamically?
TCP is a stream-based protocol. Buffer the bytes received and only extract complete messages from the stream.
For complete lines, look for newline characters in the buffer.
Example server:
import socket
class Client:
def __init__(self,socket):
self.socket = socket
self.buffer = b''
def getline(self):
# if there is no complete line in buffer,
# add to buffer until there is one.
while b'\n' not in self.buffer:
data = self.socket.recv(1024)
if not data:
# socket was closed
return ''
self.buffer += data
# break the buffer on the first newline.
# note: partition(n) return "left of n","n","right of n"
line,newline,self.buffer = self.buffer.partition(b'\n')
return line + newline
srv = socket.socket()
srv.bind(('',5000))
srv.listen(1)
conn,where = srv.accept()
client = Client(conn)
print(f'Client connected on {where}')
while True:
line = client.getline()
if not line:
break
print(line)
Example client:
s=socket()
s.connect(('127.0.0.1',5000))
s.sendall(b'line one\nline two\nline three\nincomplete')
s.close()
Output on server:
Client connected on ('127.0.0.1', 2667)
b'line one\n'
b'line two\n'
b'line three\n'

Simultaneous input and output for network based messaging program

In python, I am creating a message system where a client and server can send messages back and forth simeltaneously. Here is my code for the client:
import threading
import socket
# Global variables
host = input("Server: ")
port = 9000
buff = 1024
# Create socket instance
s = socket.socket()
# Connect to server
s.connect( (host, port) )
print("Connected to server\n")
class Recieve(threading.Thread):
def run(self):
while True: # Recieve loop
r_msg = s.recv(buff).decode()
print("\nServer: " + r_msg)
recieve_thread = Recieve()
recieve_thread.start()
while True: # Send loop
s_msg = input("Send message: ")
if s_msg.lower() == 'q': # Quit option
break
s.send( s_msg.encode() )
s.close()
I have a thread in the background to check for server messages and a looping input to send messages to the server. The problem arises when the server sends a message and the user input is immediately bounced up to make room for the servers message. I want it so that the input stays pinned to the bottom of the shell window, while the output is printed from the 2nd line up, leaving the first line alone. I have been told that you can use curses or Queues to do this, but I am not sure which one would be best in my situation nor how to implement these modules into my project.
Any help would be appreciated. Thank you.
I want it so that the input stays pinned to the bottom of the shell
window, while the output is printed from the 2nd line up, leaving the
first line alone. I have been told that you can use curses
Here's a supplemented version of your client code using curses.
import threading
import socket
# Global variables
host = input("Server: ")
port = 9000
buff = 1024
# Create socket instance
s = socket.socket()
# Connect to server
s.connect( (host, port) )
print("Connected to server\n")
import sys
write = sys.stdout.buffer.raw.write
from curses import *
setupterm()
lines = tigetnum('lines')
change_scroll_region = tigetstr('csr')
cursor_up = tigetstr('cuu1')
restore_cursor = tigetstr('rc')
save_cursor = tigetstr('sc')
def pin(input_lines): # protect input_lines at the bottom from scrolling
write(save_cursor + \
tparm(change_scroll_region, 0, lines-1-input_lines) + \
restore_cursor)
pin(1)
class Recieve(threading.Thread):
def run(self):
while True: # Recieve loop
r_msg = s.recv(buff).decode()
write(save_cursor+cursor_up)
print("\nServer: " + r_msg)
write(restore_cursor)
recieve_thread = Recieve()
recieve_thread.daemon = True
recieve_thread.start()
while True: # Send loop
s_msg = input("Send message: ")
if s_msg.lower() == 'q': # Quit option
break
s.send( s_msg.encode() )
pin(0)
s.close()
It changes the scrolling region to leave out the screen's bottom line, enters the scrolling region temporarily to output the server messages, and changes it back at the end.

Resources