1

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.

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.