1

I have been self-learning python since few months now , and finally learning Socket programming. As an text book exercise, I am supposed to design a half-duplex chat system . Below is the code. The first request and response are just fine , but everytime I try sending a second message from client, the server seems to be hanging. The program is TCP based.

I am suspecting that since ss.accept() is being called everytime a new message has to be sent, a new thread is being created but since I have made only 1 call to sc.connect() from client , may be my new connection at the server end is hanging there for infinite time.

As a trail : I called ss.accept() outside the while loop, ie making only 1 connection and listening to data over and over on while loop, the conversations works just fine

Can someone please have a look a the code and help me understand where exactly is the issue.

Since, I am learning, I have not moved to twisted yet. I want to learn all the basics first before I move to frameworks.

     !bin/usr/env python

import socket, sys
HOST =''
PORT = 1060
ADDR =(HOST,PORT)

def userinput(sock):
    usermessage = input('>')
    sock.sendall(str(len(usermessage)))
    return usermessage


def server():
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    s.bind(ADDR)
    s.listen(1)
    print 'the server is listening at',s.getsockname()

    while True:
        ss,sockname = s.accept()    
    #listen to determine the bytes sent by client
        msglen = ss.recv(4096)
    #accept the complete message
        msg = ss.recv(int(msglen))
        print 'client:', repr(msg)
        servermsg = userinput(ss)
        ss.sendall(servermsg)
        print " ---------------"
    ss.close()

def client():
    sc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    sc.connect(ADDR)    
    while True:
        message = userinput(sc)
        sc.sendall(message)
        replylen = sc.recv(4096)
        reply = sc.recv(int(replylen))
        print "reply:",reply

        print "----------------"
    sc.close()

if sys.argv[1:] == ['server']:
    server()

elif sys.argv[1:] == ['client']:
    client()
else:
    print >> sys.stderr,'usage:tcp_2_7.py server|client[host]'

1 Answer 1

1

Your trial - accepting once and then receiving multiple messages - is how you should do this. Calling accept is waiting for a new connection - you don't need to do this every time you want to send or receive a message, just as you don't want to call connect every time you want to send or receive.

Think of it this way:

When you connect to a chat server, do you connect, send a message, then disconnect immediately? No - you have a constant open connection which messages are sent through, and the connection is only closed at the end of a chat session.

From the docs on accept:

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.

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

2 Comments

@ Jozzas :Thanks for that quick explanation ! so incase I have multiple clients, thats when I will be calling the accept and connect in loop for each client ,server session.
@durga Yep! Absolutely. Libraries like twisted can make this much easier by managing the pool of connections, rather than you having to do it yourself. It's good to understand though.

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.