Task: Chat server

C: #include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <netinet/ip.h>

int tsocket;
struct sockaddr_in tsockinfo;
fd_set status, current;
void ClientText(int handle, char *buf, int buf_len);

struct client
{
    char buffer[4096];
    int pos;
    char name[32];
} *connections[FD_SETSIZE];

void AddConnection(int handle)
{
    connections[handle] = malloc(sizeof(struct client));
    connections[handle]->buffer[0] = '\0';
    connections[handle]->pos = 0;
    connections[handle]->name[0] = '\0';
}

void CloseConnection(int handle)
{
    char buf[512];
    int j;

    FD_CLR(handle, &status);
    
    if (connections[handle]->name[0])
    {
        sprintf(buf, "* Disconnected: %s\r\n", connections[handle]->name);

        for (j = 0; j < FD_SETSIZE; j++)
        {
            if (handle != j && j != tsocket && FD_ISSET(j, &status))
            {
                if (write(j, buf, strlen(buf)) < 0)
                {
                    CloseConnection(j);
                }
            }
        }
    } else
    {
        printf ("-- Connection %d disconnected\n", handle);
    }
    if (connections[handle])
    {
        free(connections[handle]);
    }
    close(handle);
}

void strip(char *buf)
{
    char *x;
    
    x = strchr(buf, '\n');
    if (x) { *x='\0'; }
    x = strchr(buf, '\r');
    if (x) { *x='\0'; }
}

int RelayText(int handle)
{
    char *begin, *end;
    int ret = 0;
    begin = connections[handle]->buffer;
    if (connections[handle]->pos == 4000)
    {
        if (begin[3999] != '\n')
            begin[4000] = '\0';
        else {
            begin[4000] = '\n';
            begin[4001] = '\0';
        }
    } else {
        begin[connections[handle]->pos] = '\0';
    }
    
    end = strchr(begin, '\n');
    while (end != NULL)
    {
        char output[8000];
        output[0] = '\0';
        if (!connections[handle]->name[0])
        {
            strncpy(connections[handle]->name, begin, 31);
            connections[handle]->name[31] = '\0';
            
            strip(connections[handle]->name);
            sprintf(output, "* Connected: %s\r\n", connections[handle]->name);
            ret = 1;
        } else 
        {
            sprintf(output, "%s: %.*s\r\n", connections[handle]->name, 
                    end-begin, begin);
            ret = 1;
        }
        
        if (output[0])
        {
            int j;
            for (j = 0; j < FD_SETSIZE; j++)
            {
                if (handle != j && j != tsocket && FD_ISSET(j, &status))
                {
                    if (write(j, output, strlen(output)) < 0)
                    {
                        CloseConnection(j);
                    }
                }
            }
        }
        begin = end+1;
        end = strchr(begin, '\n');
    }
    
    strcpy(connections[handle]->buffer, begin);
    connections[handle]->pos -= begin - connections[handle]->buffer;
    return ret;
}

void ClientText(int handle, char *buf, int buf_len)
{
    int i, j;
    if (!connections[handle])
        return;
    j = connections[handle]->pos; 
    
    for (i = 0; i < buf_len; ++i, ++j)
    {
        connections[handle]->buffer[j] = buf[i];
        
        if (j == 4000)
        {
            while (RelayText(handle));
            j = connections[handle]->pos;
        }
    }
    connections[handle]->pos = j;
    
    while (RelayText(handle));
}


int ChatLoop()
{
    int i, j;
    FD_ZERO(&status);

    FD_SET(tsocket, &status);
    FD_SET(0, &status);

    while(1)
    {
        current = status;
        if (select(FD_SETSIZE, &current, NULL, NULL, NULL)==-1)
        {
            perror("Select");
            return 0;
        }
        for (i = 0; i < FD_SETSIZE; ++i)
        {
            if (FD_ISSET(i, &current))
            {
                if (i == tsocket)
                {
                    struct sockaddr_in cliinfo;
                    socklen_t addrlen = sizeof(cliinfo);
                    int handle;
                    handle = accept(tsocket, &cliinfo, &addrlen);
                    if (handle == -1)
                    {
                        perror ("Couldn't accept connection");
                    } else if (handle > FD_SETSIZE)
                    {
                        printf ("Unable to accept new connection.\n");
                        close(handle);
                    }
                    else
                    {
                        if (write(handle, "Enter name: ", 12) >= 0)
                        {
                            printf("-- New connection %d from %s:%hu\n",
                                handle, 
                                inet_ntoa (cliinfo.sin_addr),
                                ntohs(cliinfo.sin_port));
                            FD_SET(handle, &status);

                            AddConnection(handle);
                        }
                    }
                } 
                else
                {
                    char buf[512];
                    int b;

                    b = read(i, buf, 500);
                    if (b <= 0)
                    {
                        CloseConnection(i);
                    }
                    else
                    {
                        ClientText(i, buf, b);
                    }
                }
            }
        }
    } 
}

int main (int argc, char*argv[])
{
    tsocket = socket(PF_INET, SOCK_STREAM, 0);

    tsockinfo.sin_family = AF_INET;
    tsockinfo.sin_port = htons(7070);
    if (argc > 1)
    {
        tsockinfo.sin_port = htons(atoi(argv[1]));
    }
    tsockinfo.sin_addr.s_addr = htonl(INADDR_ANY);
    printf ("Socket %d on port %hu\n", tsocket, ntohs(tsockinfo.sin_port));

    if (bind(tsocket, &tsockinfo, sizeof(tsockinfo)) == -1)
    {
        perror("Couldn't bind socket");
        return -1;
    }

    if (listen(tsocket, 10) == -1)
    {
        perror("Couldn't listen to port");
    }

    ChatLoop();

    return 0;
}







Python: 

import socket
import thread
import time

HOST = ""
PORT = 4004

def accept(conn):
    
    def threaded():
        while True:
            conn.send("Please enter your name: ")
            try:
                name = conn.recv(1024).strip()
            except socket.error:
                continue
            if name in users:
                conn.send("Name entered is already in use.\n")
            elif name:
                conn.setblocking(False)
                users[name] = conn
                broadcast(name, "+++ %s arrived +++" % name)
                break
    thread.start_new_thread(threaded, ())

def broadcast(name, message):
    
    print message
    for to_name, conn in users.items():
        if to_name != name:
            try:
                conn.send(message + "\n")
            except socket.error:
                pass


server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.setblocking(False)
server.bind((HOST, PORT))
server.listen(1)
print "Listening on %s" % ("%s:%s" % server.getsockname())


users = {}
while True:
    try:
        
        while True:
            try:
                conn, addr = server.accept()
            except socket.error:
                break
            accept(conn)
        
        for name, conn in users.items():
            try:
                message = conn.recv(1024)
            except socket.error:
                continue
            if not message:
                
                del users[name]
                broadcast(name, "--- %s leaves ---" % name)
            else:
                broadcast(name, "%s> %s" % (name, message.strip()))
        time.sleep(.1)
    except (SystemExit, KeyboardInterrupt):
        break