0

I have a project in which I need to make a simple chat with sending files via sockets. I would like to know if there is any function in socket programming in C that would allow me to check for existing connections (I need to send messages to every client that is connected). I tried to do it by making an array and save my socket to it, but because of fork() it doesn't work, every client has its own array and they are not matching. My server is written in C and my client is written in Python. Below is my code:

Server:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 9992

int main(){
    char separator[4];
    int iterator = 0;
    int clients[32];
    separator[0] = '|';
    int sockfd, ret;
    char name[32];
     struct sockaddr_in serverAddr;

    int newSocket;
    struct sockaddr_in newAddr;

    socklen_t addr_size;

    char buffer[1024];
    pid_t childpid;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0){
        printf("[-]Error in connection.\n");
        exit(1);
    }
    printf("[+]Server Socket is created.\n");

    memset(&serverAddr, '\0', sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(PORT);
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if(ret < 0){
        perror("");
        printf("[-]Error in binding.\n");
        exit(1);
    }
    printf("[+]Bind to port %d\n", PORT);

    if(listen(sockfd, 10) == 0){
        printf("[+]Listening....\n");
    }else{
        perror("");
        printf("[-]Error in binding.------\n");
    }


    while(1){
        newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
        printf("%i", newSocket);

        for (size_t i = 0; i <= iterator; i++) {
            // printf("%i\n", iterator);
            if(clients[i] == 0){
                clients[i] = newSocket;
            }
            else if(i == iterator){
                clients[iterator] = newSocket;
                iterator ++;
                break;
            }
        }

        if(newSocket < 0){
            perror("");
            printf("new socket < 0");
            exit(1);
        }
        printf("Connection accepted from %s:%d ", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
        recv(newSocket, name, 32, 0 );
        printf("%s \n", name);
        if((childpid = fork()) == 0){
            // perror("");
            // close(sockfd);

            while(1){
                for (size_t i = 0; i < iterator; i++) {
                    printf("%i\n", clients[i]);
                }
                recv(newSocket, buffer, 1024, 0);
                if(strcmp(buffer, "/exit") == 0){
                    printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
                    perror("");
                    // deleting disconnecting client from array of clients
                    for (int i = 0; i < iterator; i++) {
                        // printf(clients[i]);
                        if(clients[i] == newSocket){
                            clients[i] = 0;
                            printf("Element deleted \n");
                        }
                        break;
                    }
                    break;
                }else{

                    if(strcmp(buffer, "/who") == 0){
                        perror("");
                        for (size_t i = 0; i < iterator; i++) {
                            printf("%i\n", clients[i]);
                            bzero(buffer, sizeof(buffer));
                        }
                    }
                    perror("");
                    printf("%s: %s\n",name, buffer);
                    for (size_t i = 0; i < iterator; i++) //sending message to every client {
                        send(clients[i], name, strlen(name), 0);
                        send(clients[i], separator, strlen(separator), 0);
                        send(clients[i], buffer, strlen(buffer), 0);

                    }
                    bzero(buffer, sizeof(buffer));
                    // bzero(name, sizeof(name));

                }
            }
        }

    }

    close(newSocket);
    // perror("");

    return 0;
}

My client.py:

import socket
import sys
import time

host = '127.0.0.1'
port = 9992
buffer = ''
# create socket
print('# Creating socket')
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
    print('Failed to create socket')
    sys.exit()

print('# Getting remote IP address')
try:
    remote_ip = socket.gethostbyname( host )
except socket.gaierror:
    print('Hostname could not be resolved. Exiting')
    sys.exit()

# Connect to remote server
print('# Connecting to server, ' + host + ' (' + remote_ip + ')')
name = input("What will be your name?: ")
namePY = name
name += "\0"
s.connect((remote_ip , port))
s.send(name.encode())



# Send data to remote server
print('Connection established with server, your name is: {}'.format(name))
while True:
    buffer = input("{}: ".format(namePY))
    buffer += '\0'
    s.send(buffer.encode())
    if(buffer == "/exit\0"):
        s.close()
        break
    # print('# Receive data from server')
    time.sleep(0.1)
    reply = s.recv(1024).decode()
    replyArray = reply.split('|')
    if replyArray[0] == namePY:
        pass
    else:
        print('{}: {}'.format(replyArray[0], replyArray[1]))

kapisolec
  • 123
  • 12
  • What does "check for existing connections" mean? As far as sockets go, the only system calls that involve sockets are `socket()`, `bind()`, `listen()`, and `connect()`, and `accept()`. – Sam Varshavchik Dec 05 '20 at 16:46
  • 1
    Yeahh....you already have many fails, eg 'recv(newSocket, buffer, 1024, 0);' -you MUST correctly and completely handle the result returned from system calls like send(), recv(). If a C library function requires a NUL-terminated char array, you MUST ensure that such arguments are guaranteed NUL-terminated. – Martin James Dec 05 '20 at 16:46
  • 1
    You should first read more about TCP/IP. And you should use muilti-thread for incomming clients - look at accept and provide a thread for each Client-Com. The socket from the accept store in a list or simliar. Now you can iterate over all sockets in the list and send/receive messages. You also need more Exception-Handling for server and client: Client disconnect, sever shutdown socket and so on. – raiserle Dec 05 '20 at 16:54
  • Even if the server implementation is here in PYTHON: You can also adapt it to C: https://stackoverflow.com/questions/10810249/python-socket-multiple-clients Once you have done that, we can talk about the data you want to send/receive – raiserle Dec 05 '20 at 16:58

1 Answers1

5

For a multi-client network server in which different clients are interacting with each other, using a multi-thread design will be easier than a multi-process design like you have there. By spawning a new thread per client in the same process, you’ll be able to share memory structures over all threads. For multiple processes, you’d have to use things like pipes or shared memory segments, which are more difficult (even considering the need for synchronization primitives like mutexes in the multi-thread case). Additionally, there’s no way for one process to write directly to another process’ sockets. The best it could do would be to ask the other processes to do the writing.

Sneftel
  • 40,271
  • 12
  • 71
  • 104