Reputation: 123
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]))
Upvotes: 0
Views: 673
Reputation: 41454
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.
Upvotes: 5