Problem is to make UDP server send data to an array of clients, that already make a connection to a server. All clients IPs are stored on the server side linkedlist, but for some reason, i am able to send response only, and only to the last made connection from the client.
So basic description of what I want to achieve is:
few clients made a connection and i can see their messages
every client's IP is stored in linkedlist
if there is more than 1 client stored in linkedlist, program will go through every IP in its storage, and if IP of current client is DIFFERENT from what is stored in linkedlist -> server is sending to this IP last message from current client
on the server side, if message was typed, program will go through every IP stored in LinkedList and send this message to every client
server.c
#include "server.h"
#include "linkedList.h"
volatile sig_atomic_t dones = 0;
void server(){
pthread_t r, s;
int server_d;
struct sockaddr_in server, client;
struct params args;
linkedList** iter = getIteratorList();
if((server_d = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
perror("\nsocket");
exit(-1);
}
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = INADDR_ANY;
bzero(server.sin_zero, 8);
args.client = &client;
args.server_d = &server_d;
args.iter = iter;
if(bind(server_d, (struct sockaddr*)&server, sizeof(struct sockaddr)) == -1){
perror("\nbind");
exit(-1);
}
pthread_create(&r, NULL, receives, (void*)&args);
pthread_create(&s, NULL, sends, (void*)&args);
pthread_join(s, NULL);
}
void* receives(void* data){
int flag = 0;
struct params* args = data;
int* server_d = args->server_d;
struct sockaddr_in* client = args->client;
linkedList** iter = args->iter;
unsigned int length = sizeof(struct sockaddr_in);
char buffer[BUFFER_MAX];
struct sockaddr_in tmp;
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = terms;
sigaction(SIGINT, &action, NULL);
bzero(buffer, BUFFER_MAX);
while(!dones){
if(flag == 0){
if(recvfrom(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)client, &length) > 0){
flag = 1;
decrypt(buffer);
printf("[%s]:%s", inet_ntoa(client->sin_addr), buffer);
//some new staff
if(checkList(inet_ntoa(client->sin_addr)) != 1){
addList(*client);
printf("[DEBUG]clients IP is stored. size of LL: %d\n", sizeList());
}
if(sizeList() > 1){
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[DEBUG]Stored IP[%d]: %s\n", i, (*iter)->address);
nextList();
}
}
beginList();
for(int i = 0; i < sizeList(); i++){
if (strcmp((*iter)->address, inet_ntoa(client->sin_addr)) != 0){
printf("[DEBUG]there is a client to send a message to. message: %s", buffer);
printf("[DEBUG]resend: %s --> %s\n",inet_ntoa(client->sin_addr), (*iter)->address);
tmp.sin_addr.s_addr = inet_addr((*iter)->address);
tmp.sin_family = client->sin_family;
tmp.sin_port = client->sin_port;
bzero(tmp.sin_zero, 8);
printf("[DEBUG]IP in tmp.sin_addr: %s\n", inet_ntoa(tmp.sin_addr));
printf("[DEBUG]IP in client->sin_addr: %s\n", inet_ntoa(client->sin_addr));
printf("[DEBUG]message send: %d\n", (int)sendto(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)&tmp, sizeof(struct sockaddr_in)));
nextList();
}else{
nextList();
}
}
// end of new staff
}
bzero(buffer, BUFFER_MAX);
}else{
if(recvfrom(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)client, &length) == 0){
flag = 0;
}else{
decrypt(buffer);
printf("[%s]:%s", inet_ntoa(client->sin_addr), buffer);
//some new staff
if(checkList(inet_ntoa(client->sin_addr)) != 1){
addList(*client);
printf("[DEBUG]clients IP is stored. size of LL: %d\n", sizeList());
}
if(sizeList() > 1){
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[DEBUG]Stored IP[%d]: %s\n", i, (*iter)->address);
nextList();
}
}
beginList();
for(int i = 0; i < sizeList(); i++){
if (strcmp((*iter)->address, inet_ntoa(client->sin_addr)) != 0){
printf("[DEBUG]there is a client to send a message to. message: %s", buffer);
printf("[DEBUG]resend: %s --> %s\n",inet_ntoa(client->sin_addr), (*iter)->address);
tmp.sin_addr.s_addr = inet_addr((*iter)->address);
tmp.sin_family = client->sin_family;
tmp.sin_port = client->sin_port;
bzero(tmp.sin_zero, 8);
printf("[DEBUG]IP in tmp.sin_addr: %s\n", inet_ntoa(tmp.sin_addr));
printf("[DEBUG]IP in client->sin_addr: %s\n", inet_ntoa(client->sin_addr));
printf("[DEBUG]message send: %d\n", (int)sendto(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)&tmp, sizeof(struct sockaddr_in)));
nextList();
}else{
nextList();
}
}
// end of new staff
}
bzero(buffer, BUFFER_MAX);
}
}
printf("Server terminated.\n");
return NULL;
}
void* sends(void* data){
struct params* args = data;
int* server_d = args->server_d;
struct sockaddr_in* client = args->client;
linkedList** iter = args->iter;
char buffer[BUFFER_MAX];
struct sockaddr_in tmp;
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = terms;
sigaction(SIGINT, &action, NULL);
while(!dones){
bzero(buffer, BUFFER_MAX);
fgets(buffer, BUFFER_MAX - 1, stdin);
encrypt(buffer);
/*
if(sendto(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)client, sizeof(struct sockaddr_in)) == -1){
printf("Message was not sent...\n");
}
*/
tmp.sin_addr.s_addr = client->sin_addr.s_addr;
tmp.sin_family = client->sin_family;
tmp.sin_port = client->sin_port;
bzero(tmp.sin_zero, 8);
beginList();
for(int i = 0; i < sizeList(); i++){
tmp.sin_addr.s_addr = inet_addr((*iter)->address);
printf("[DEBUG]sending to address: %s\n", inet_ntoa(tmp.sin_addr));
sendto(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)&tmp, sizeof(struct sockaddr_in));
nextList();
}
}
printf("Server terminated.\n");
return NULL;
}
void terms(int signum){
dones = 1;
if(clearList() == 0) printf("\n\nLinkedList was succesfully deleted.\n");
printf("\nTerminating server...\n");
}
server.h
#ifndef SERVER_H_
#define SERVER_H_
#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>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include "const.h"
#include "encrypt.h"
#include "linkedList.h"
struct params{
struct sockaddr_in* client;
int* server_d;
linkedList** iter;
};
volatile sig_atomic_t dones;
void server();
void* receives(void*);
void* sends(void*);
void terms(int);
#endif
linkedList.h
#ifndef LINKED_LIST_
#define LINKED_LIST_
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
typedef struct ll{
int socket;
char* address;
struct ll* next;
struct ll* prev;
} linkedList;
linkedList* initList(struct sockaddr_in);
linkedList* addList(struct sockaddr_in);
linkedList* removeList(char*);
unsigned short int clearList();
unsigned short int sizeList();
linkedList* nextList();
linkedList* prevList();
linkedList* beginList();
linkedList* endList();
linkedList** getIteratorList();
unsigned short int checkList(char*);
#endif
linkedList.c
#include "linkedList.h"
static linkedList* iterator = NULL;
linkedList* initList(struct sockaddr_in p_new){
iterator = (linkedList*) malloc(sizeof(linkedList));
if(iterator == NULL) return NULL;
iterator->next = NULL;
iterator->prev = NULL;
iterator->address = (char*)malloc(sizeof(char)*16);
strcpy(iterator->address, inet_ntoa(p_new.sin_addr));
return iterator;
}
linkedList* addList(struct sockaddr_in p_new){
if(iterator == NULL){
return initList(p_new);
}
endList();
iterator->next = (linkedList*) malloc(sizeof(linkedList));
if(iterator->next == NULL) return NULL;
iterator->next->next = NULL;
iterator->next->prev = iterator;
iterator->next->address = (char*)malloc(sizeof(char)*16);
strcpy(iterator->next->address, inet_ntoa(p_new.sin_addr));
return iterator = iterator->next;
}
linkedList* removeList(char* p_address){
beginList();
for(int i = 0; i < sizeList(); i++){
if(strcmp(iterator->address, p_address) == 0){
if(iterator->prev == NULL){
iterator = iterator->next;
free(iterator->prev->address);
free(iterator->prev);
iterator->prev = NULL;
return iterator;
}else if(iterator->next == NULL){
iterator = iterator->prev;
free(iterator->next->address);
free(iterator->next);
iterator->next = NULL;
return iterator;
}else{
linkedList* tmp = iterator->next;
iterator->prev->next = iterator->next;
iterator->next->prev = iterator->prev;
free(iterator->address);
free(iterator);
return iterator = tmp;
}
}else{
nextList();
}
}
beginList();
return iterator;
}
unsigned short int clearList(){
if (iterator == NULL) return 404;
endList();
while( (iterator->next != NULL && iterator->prev != NULL) ){
iterator = iterator->prev;
free(iterator->next->address);
free(iterator->next);
iterator->next = NULL;
}
free(iterator);
iterator = NULL;
return 0;
}
unsigned short int sizeList(){
unsigned short int size = 0;
unsigned int tmp_range = 0;
if(iterator == NULL) return size;
while(iterator->prev != NULL){
tmp_range++;
prevList();
}
while(iterator->next != NULL){
size++;
nextList();
}
size++;
beginList();
for(int i = 0; i < tmp_range; i++){
nextList();
}
return size;
}
linkedList* nextList(){
if (iterator == NULL) return NULL;
if(iterator->next == NULL) return iterator; else return iterator = iterator->next;
}
linkedList* prevList(){
if (iterator == NULL) return NULL;
if(iterator->prev == NULL) return iterator; else return iterator = iterator->prev;
}
linkedList* beginList(){
if (iterator == NULL) return NULL;
while(iterator->prev != NULL){
prevList();
}
return iterator;
}
linkedList* endList(){
if (iterator == NULL) return NULL;
while(iterator->next != NULL){
nextList();
}
return iterator;
}
linkedList** getIteratorList(){
return &iterator;
}
unsigned short int checkList(char* p_str){
if(iterator == NULL) return 0;
beginList();
for(int i = 0; i < sizeList(); i++){
if(strcmp(iterator->address, p_str) == 0){
return 1;
}else nextList();
}
beginList();
return 0;
}
client.h
#ifndef CLIENT_H_
#define CLIENT_H_
#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>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include "const.h"
#include "encrypt.h"
struct paramc{
struct sockaddr_in* server;
int* client_d;
};
volatile sig_atomic_t donec;
void client(char*);
void* receivec(void*);
void* sendc(void*);
void termc(int);
#endif
client.c
#include "client.h"
volatile sig_atomic_t donec = 0;
void client(char* address){
pthread_t r, s;
int client_d;
struct sockaddr_in server;
struct paramc args;
if((client_d = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
perror("\nsocket");
exit(-1);
}
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = inet_addr(address);
bzero(server.sin_zero, 8);
args.server = &server;
args.client_d = &client_d;
pthread_create(&r, NULL, receivec, (void*)&args);
pthread_create(&s, NULL, sendc, (void*)&args);
pthread_join(s, NULL);
}
void* receivec(void* data){
struct paramc* args = data;
struct sockaddr_in* server = args->server;
int* client_d = args->client_d;
unsigned int length = sizeof(struct sockaddr_in);
char buffer[BUFFER_MAX];
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = termc;
sigaction(SIGINT, &action, NULL);
while(!donec){
if(recvfrom(*client_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)server, &length) > 0){
decrypt(buffer);
printf("[%s]:%s", inet_ntoa(server->sin_addr), buffer);
bzero(buffer, BUFFER_MAX);
}
}
printf("Client terminated.\n");
return NULL;
}
void* sendc(void* data){
struct paramc* args = data;
struct sockaddr_in* server = args->server;
int* client_d = args->client_d;
char buffer[BUFFER_MAX];
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = termc;
sigaction(SIGINT, &action, NULL);
while(!donec){
bzero(buffer, BUFFER_MAX);
fgets(buffer, BUFFER_MAX - 1, stdin);
encrypt(buffer);
sendto(*client_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)server, sizeof(struct sockaddr_in));
}
printf("Client terminated.\n");
return NULL;
}
void termc(int signum){
donec = 1;
printf("\nTerminating client...\n");
}
const.h
#ifndef CONST_H_
#define CONST_H_
#define PORT 15151
#define BUFFER_MAX 1024
#endif
main.c
#include "server.h"
#include "client.h"
//#define linkedlist_test
#ifdef linkedlist_test
#include "linkedList.h"
#endif
int main(int argc, char* argv[]){
#ifndef linkedlist_test
system("clear");
if(argc < 2){
server();
}else{
client(argv[1]);
}
#endif
#ifdef linkedlist_test
struct sockaddr_in test1;
test1.sin_family = AF_INET;
test1.sin_port = htons(PORT);
test1.sin_addr.s_addr = inet_addr("192.168.1.101");
bzero(test1.sin_zero, 8);
struct sockaddr_in test2;
test2.sin_family = AF_INET;
test2.sin_port = htons(PORT);
test2.sin_addr.s_addr = inet_addr("192.168.1.102");
bzero(test2.sin_zero, 8);
struct sockaddr_in test3;
test3.sin_family = AF_INET;
test3.sin_port = htons(PORT);
test3.sin_addr.s_addr = inet_addr("192.168.1.103");
bzero(test3.sin_zero, 8);
struct sockaddr_in test4;
test4.sin_family = AF_INET;
test4.sin_port = htons(PORT);
test4.sin_addr.s_addr = inet_addr("192.168.1.104");
bzero(test4.sin_zero, 8);
struct sockaddr_in test5;
test5.sin_family = AF_INET;
test5.sin_port = htons(PORT);
test5.sin_addr.s_addr = inet_addr("192.168.1.105");
bzero(test5.sin_zero, 8);
linkedList** iterator = getIteratorList();
printf("address: %p/%p\torder: %d\n", *iterator, addList(test1), sizeList());
printf("address: %p/%p\torder: %d\n", *iterator, addList(test2), sizeList());
printf("address: %p/%p\torder: %d\n", *iterator, addList(test3), sizeList());
printf("address: %p/%p\torder: %d\n", *iterator, addList(test4), sizeList());
printf("address: %p/%p\torder: %d\n", *iterator, addList(test5), sizeList());
printf("vypis testovych struktur priamo:\n%s\n", inet_ntoa(test1.sin_addr));
printf("%s\n", inet_ntoa(test2.sin_addr));
printf("%s\n", inet_ntoa(test3.sin_addr));
printf("%s\n", inet_ntoa(test4.sin_addr));
printf("%s\n", inet_ntoa(test5.sin_addr));
printf("========================\n");
checkList("192.168.1.104");
printf("checkList() test: adresa -//-.104 sa nachadza: %p, plna adresa je %s\n", (*iterator), (*iterator)->address);
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[%p]list\'s output [%d]: %s\n", *iterator, i, (*iterator)->address);
nextList();
}
printf("========================\n");
removeList("192.168.1.102");
printf("deleting 192.168.1.102\n");
printf("size: %d\n", sizeList());
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[%p]list\'s output [%d]: %s\n", *iterator, i, (*iterator)->address);
nextList();
}
printf("========================\n");
removeList("192.168.1.101");
printf("deleting 192.168.1.101\n");
printf("size: %d\n", sizeList());
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[%p]list\'s output [%d]: %s\n", *iterator, i, (*iterator)->address);
nextList();
}
printf("========================\n");
removeList("192.168.1.105");
printf("deleting 192.168.1.105\n");
printf("size: %d\n", sizeList());
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[%p]list\'s output [%d]: %s\n", *iterator, i, (*iterator)->address);
nextList();
}
printf("========================\n");
printf("removing the whole list\n");
if(clearList() == 0) printf("successfully removed\n"); else printf("some chiki-briki is not right. FAILUREEE!");
printf("size: %d\n", sizeList());
printf("========================\n");
#endif
return 0;
}
encrypt.c and encrypt.h are just two functions char* encrypt(char*) and char* decrypt(char*) that did nothing with a string --> WIP
Related
There are two clients and a server in the application. The two clients communicate with each other via the server. When one client sends a message to the server, the server stores the message as a text file in the server, where file name is clientid_timestamp.txt. The server then sends the file to the other client that reads the file and displays its content on its terminal.
I have written the code for the client and the server given below.The issue that I am facing is that the client is not able to get the file from the server print it's contents.It doesn't show an output in the terminal.
Server side image in terminal
client side image in terminal
Server code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <signal.h>
#define MAX_CLIENTS 3
#define BUFFER_SZ 2048
#define SIZE 1024
static _Atomic unsigned int cli_count = 0;
static int uid = 10;
/* Client structure */
typedef struct{
struct sockaddr_in address;
int sockfd;
int uid;
char name[32];
} client_t;
client_t *clients[MAX_CLIENTS];
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
void str_overwrite_stdout() {
printf("\r%s", "> ");
fflush(stdout);
}
void print_client_addr(struct sockaddr_in addr){
printf("%d.%d.%d.%d",
addr.sin_addr.s_addr & 0xff,
(addr.sin_addr.s_addr & 0xff00) >> 8,
(addr.sin_addr.s_addr & 0xff0000) >> 16,
(addr.sin_addr.s_addr & 0xff000000) >> 24);
}
/* Add clients to queue */
void queue_add(client_t *cl){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(!clients[i]){
clients[i] = cl;
break;
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Remove clients to queue */
void queue_remove(int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid == uid){
clients[i] = NULL;
break;
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
void send_file(int sockfd){
int n;
char data[SIZE] = {0};
FILE *fp = fopen("clientid_timestamp.txt", "r");
if (fp == NULL){
printf("Error opening file!\n");
exit(1);
}
while(fgets(data, SIZE, fp) != NULL) {
if (send(sockfd, data, sizeof(data), 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
printf("hello");
bzero(data, SIZE);
}
}
/* Send message to all clients except sender */
void send_message(char *s, int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i<MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid != uid){
printf("MESSAGE SENT TO %s:%d \n",inet_ntoa(clients[i]->address.sin_addr),ntohs(clients[i]->address.sin_port));
send_file(clients[i]->uid);
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Handle all communication with the client */
void *handle_client(void *arg){
char buff_out[BUFFER_SZ];
char name[32];
int leave_flag = 0;
cli_count++;
client_t *cli = (client_t *)arg;
// Name
bzero(buff_out, BUFFER_SZ);
while(1){
if (leave_flag) {
break;
}
int receive = recv(cli->sockfd, buff_out, BUFFER_SZ, 0);
if (receive > 0){
if(strlen(buff_out) > 0){
FILE *f = fopen("clientid_timestamp.txt", "w");
if (f == NULL){
printf("Error opening file!\n");
exit(1);
}
/* print some text */
fprintf(f, "%s", buff_out);
send_message(buff_out, cli->uid);
fclose(f);
printf("\n");
}
}
else {
printf("ERROR: -1\n");
leave_flag = 1;
}
bzero(buff_out, BUFFER_SZ);
}
/* Delete client from queue and yield thread */
close(cli->sockfd);
queue_remove(cli->uid);
free(cli);
cli_count--;
pthread_detach(pthread_self());
return NULL;
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
int option = 1;
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
pthread_t tid;
/* Socket settings */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(ip);
serv_addr.sin_port = htons(port);
/* Ignore pipe signals */
signal(SIGPIPE, SIG_IGN);
if(setsockopt(listenfd, SOL_SOCKET,(SO_REUSEPORT | SO_REUSEADDR),(char*)&option,sizeof(option)) < 0){
perror("ERROR: setsockopt failed");
return EXIT_FAILURE;
}
/* Bind */
if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR: Socket binding failed");
return EXIT_FAILURE;
}
/* Listen */
if (listen(listenfd, 10) < 0) {
perror("ERROR: Socket listening failed");
return EXIT_FAILURE;
}
printf("=== WELCOME TO THE CHATROOM ===\n");
char exit[] = "exit_client";
char accepted[] = "accept_client";
while(1){
socklen_t clilen = sizeof(cli_addr);
connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);
/* Check if max clients is reached */
if((cli_count) == MAX_CLIENTS){
printf("Max clients reached. Rejected: ");
print_client_addr(cli_addr);
printf(":%d\n", cli_addr.sin_port);
send(connfd, exit, strlen(exit), 0);
close(connfd);
continue;
}
else{
send(connfd, accepted, strlen(accepted), 0);
client_t *cli = (client_t *)malloc(sizeof(client_t));
cli->address = cli_addr;
cli->sockfd = connfd;
cli->uid = uid++;
printf("Client Connected : ");
printf("%s:%d \n",inet_ntoa(cli->address.sin_addr),ntohs(cli->address.sin_port));
/* Add client to the queue and fork thread */
queue_add(cli);
pthread_create(&tid, NULL, &handle_client, (void*)cli);
/* Reduce CPU usage */
sleep(1);
}
/* Client settings */
}
return EXIT_SUCCESS;
}
Client Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define LENGTH 2048
#define MAX 10000
// Global variables
volatile sig_atomic_t flag = 0;
int sockfd = 0;
char name[32];
void str_overwrite_stdout() {
printf("%s", "> ");
fflush(stdout);
}
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
void catch_ctrl_c_and_exit(int sig) {
flag = 1;
}
void send_msg_handler() {
char message[LENGTH] = {};
char buffer[LENGTH + 32] = {};
while(1) {
str_overwrite_stdout();
fgets(message, LENGTH, stdin);
//str_trim_lf(message, LENGTH);
if (strcmp(message, "exit") == 0) {
break;
} else {
sprintf(buffer, "%s\n", message);
send(sockfd, buffer, strlen(buffer), 0);
}
bzero(message, LENGTH);
bzero(buffer, LENGTH + 32);
}
catch_ctrl_c_and_exit(2);
}
void recv_msg_handler() {
while (1) {
int n;
FILE *fp;
char buff[1024]="",*ptr=buff;
int bytes=0,bytes_received;
while(bytes_received = recv(sockfd,ptr, 1, 0)){
printf("%s\n",ptr);
if(bytes_received==-1){
perror("recieve");
exit(3);
}
if(*ptr=='\n' ) break;
ptr++; //each times we increment it it points to the buffer element
}
*ptr=0;
ptr=buff;
printf("%s\n",ptr);
str_overwrite_stdout();
}
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
signal(SIGINT, catch_ctrl_c_and_exit);
struct sockaddr_in server_addr;
/* Socket settings */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_port = htons(port);
// Connect to Server
int err = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (err == -1) {
printf("ERROR: connect\n");
return EXIT_FAILURE;
}
char exit_client[] = "exit_client";
char buff[MAX];
bzero(buff, sizeof(buff));
recv(sockfd, buff, 1024, 0);
if((strcmp(buff, exit_client) == 0)){
printf("limit exceeded , closing the client \n");
close(sockfd);
return EXIT_SUCCESS;
}
else{
printf("client accepted by the server and limit not exceeded \n");
}
printf("=== WELCOME TO THE CHATROOM ===\n");
pthread_t send_msg_thread;
if(pthread_create(&send_msg_thread, NULL, (void *) send_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
pthread_t recv_msg_thread;
if(pthread_create(&recv_msg_thread, NULL, (void *) recv_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
while (1){
if(flag){
printf("\nBye\n");
break;
}
}
close(sockfd);
return EXIT_SUCCESS;
}
EDIT-1
I have made the changes suggested by the user stackinside and the code now works , but I have being facing a new issue for the past few hours and I am not able to wrap my head around it as what could the reason for it.
The issue that arises now is that the client is only able to send the message once to other client and vice versa and then it is not able to send any more messages except a new line.The updated code based on the changes I made
client side image in terminal
server side image in terminal
Server code :
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <signal.h>
#define MAX_CLIENTS 3
#define BUFFER_SZ 2048
#define SIZE 1024
static _Atomic unsigned int cli_count = 0;
static int uid = 10;
/* Client structure */
typedef struct{
struct sockaddr_in address;
int sockfd;
int uid;
char name[32];
} client_t;
client_t *clients[MAX_CLIENTS];
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
void str_overwrite_stdout() {
printf("\r%s", "> ");
fflush(stdout);
}
void print_client_addr(struct sockaddr_in addr){
printf("%d.%d.%d.%d",
addr.sin_addr.s_addr & 0xff,
(addr.sin_addr.s_addr & 0xff00) >> 8,
(addr.sin_addr.s_addr & 0xff0000) >> 16,
(addr.sin_addr.s_addr & 0xff000000) >> 24);
}
/* Add clients to queue */
void queue_add(client_t *cl){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(!clients[i]){
clients[i] = cl;
break;
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Remove clients to queue */
void queue_remove(int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid == uid){
clients[i] = NULL;
break;
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
void send_file(int sockfd){
int n;
char data[SIZE] = {0};
FILE *fp = fopen("clientid_timestamp.txt", "r");
if (fp == NULL){
printf("Error opening file!\n");
exit(1);
}
while(fgets(data, SIZE, fp) != NULL) {
if (send(sockfd, data, sizeof(data), 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
bzero(data, SIZE);
}
}
/* Send message to all clients except sender */
void send_message(char *s, int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i<MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid != uid){
printf("MESSAGE SENT TO %s:%d \n",inet_ntoa(clients[i]->address.sin_addr),ntohs(clients[i]->address.sin_port));
send_file(clients[i]->sockfd);
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Handle all communication with the client */
void *handle_client(void *arg){
char buff_out[BUFFER_SZ];
char name[32];
int leave_flag = 0;
cli_count++;
client_t *cli = (client_t *)arg;
// Name
bzero(buff_out, BUFFER_SZ);
while(1){
if (leave_flag) {
break;
}
int receive = recv(cli->sockfd, buff_out, BUFFER_SZ, 0);
if (receive > 0){
if(strlen(buff_out) > 0){
FILE *f = fopen("clientid_timestamp.txt", "w");
if (f == NULL){
printf("Error opening file!\n");
exit(1);
}
/* print some text */
fprintf(f, "%s", buff_out);
fclose(f);
send_message(buff_out, cli->uid);
printf("\n");
}
}
else {
printf("ERROR: -1\n");
leave_flag = 1;
}
bzero(buff_out, BUFFER_SZ);
}
/* Delete client from queue and yield thread */
close(cli->sockfd);
queue_remove(cli->uid);
free(cli);
cli_count--;
pthread_detach(pthread_self());
return NULL;
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
int option = 1;
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
pthread_t tid;
/* Socket settings */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(ip);
serv_addr.sin_port = htons(port);
/* Ignore pipe signals */
signal(SIGPIPE, SIG_IGN);
if(setsockopt(listenfd, SOL_SOCKET,(SO_REUSEPORT | SO_REUSEADDR),(char*)&option,sizeof(option)) < 0){
perror("ERROR: setsockopt failed");
return EXIT_FAILURE;
}
/* Bind */
if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR: Socket binding failed");
return EXIT_FAILURE;
}
/* Listen */
if (listen(listenfd, 10) < 0) {
perror("ERROR: Socket listening failed");
return EXIT_FAILURE;
}
printf("=== WELCOME TO THE CHATROOM ===\n");
char exit[] = "exit_client";
char accepted[] = "accept_client";
while(1){
socklen_t clilen = sizeof(cli_addr);
connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);
/* Check if max clients is reached */
if((cli_count) == MAX_CLIENTS){
printf("Max clients reached. Rejected: ");
print_client_addr(cli_addr);
printf(":%d\n", cli_addr.sin_port);
send(connfd, exit, strlen(exit), 0);
close(connfd);
continue;
}
else{
send(connfd, accepted, strlen(accepted), 0);
client_t *cli = (client_t *)malloc(sizeof(client_t));
cli->address = cli_addr;
cli->sockfd = connfd;
cli->uid = uid++;
printf("Client Connected : ");
printf("%s:%d \n",inet_ntoa(cli->address.sin_addr),ntohs(cli->address.sin_port));
/* Add client to the queue and fork thread */
queue_add(cli);
pthread_create(&tid, NULL, &handle_client, (void*)cli);
/* Reduce CPU usage */
sleep(1);
}
/* Client settings */
}
return EXIT_SUCCESS;
}
Client code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define LENGTH 2048
#define MAX 10000
// Global variables
volatile sig_atomic_t flag = 0;
int sockfd = 0;
char name[32];
void str_overwrite_stdout() {
printf("%s", "> ");
fflush(stdout);
}
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
void catch_ctrl_c_and_exit(int sig) {
flag = 1;
}
void send_msg_handler() {
char message[LENGTH] = {};
char buffer[LENGTH + 32] = {};
while(1) {
str_overwrite_stdout();
fgets(message, LENGTH, stdin);
str_trim_lf(message, LENGTH);
if (strcmp(message, "exit") == 0) {
break;
} else {
sprintf(buffer, "%s\n", message);
send(sockfd, buffer, strlen(buffer), 0);
}
bzero(message, LENGTH);
bzero(buffer, LENGTH + 32);
}
catch_ctrl_c_and_exit(2);
}
void recv_msg_handler() {
int n;
FILE *fp;
char buff[1024]="",*ptr=buff;
int bytes=0,bytes_received;
while (1) {
while(bytes_received = recv(sockfd,ptr, 1, 0)){
if(bytes_received==-1){
perror("recieve");
exit(3);
}
if(*ptr=='\n' ) break;
ptr++; //each times we increment it it points to the buffer element
}
*ptr=0;
str_trim_lf(buff, strlen(buff));
ptr=buff;
printf("%s \n",ptr);
str_overwrite_stdout();
}
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
signal(SIGINT, catch_ctrl_c_and_exit);
struct sockaddr_in server_addr;
/* Socket settings */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_port = htons(port);
// Connect to Server
int err = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (err == -1) {
printf("ERROR: connect\n");
return EXIT_FAILURE;
}
char exit_client[] = "exit_client";
char buff[MAX];
bzero(buff, sizeof(buff));
recv(sockfd, buff, 1024, 0);
if((strcmp(buff, exit_client) == 0)){
printf("limit exceeded , closing the client \n");
close(sockfd);
return EXIT_SUCCESS;
}
else{
printf("client accepted by the server and limit not exceeded \n");
}
printf("=== WELCOME TO THE CHATROOM ===\n");
pthread_t send_msg_thread;
if(pthread_create(&send_msg_thread, NULL, (void *) send_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
pthread_t recv_msg_thread;
if(pthread_create(&recv_msg_thread, NULL, (void *) recv_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
while (1){
if(flag){
printf("\nBye\n");
break;
}
}
close(sockfd);
return EXIT_SUCCESS;
}
EDIT-2
So now I changed the fgets to freads and removed all the unnecessary bzero and changed the strlen to sizeof as suggested by the comments of user207421 , Martin James and stackinside .It finally works , I agree there is still a lot of room for optimisation , but it works for now and thanks for the effort.
client side image in terminal
Server side image in terminal
Client side code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define LENGTH 2048
#define MAX 10000
#define CHUNK_SIZE 512
// Global variables
volatile sig_atomic_t flag = 0;
int sockfd = 0;
char name[32];
void str_overwrite_stdout() {
printf("%s", "> ");
fflush(stdout);
}
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
void catch_ctrl_c_and_exit(int sig) {
flag = 1;
}
void send_msg_handler() {
char message[LENGTH] = {};
char buffer[LENGTH + 32] = {};
while(1) {
str_overwrite_stdout();
fgets(message, LENGTH, stdin);
str_trim_lf(message, LENGTH);
if (strcmp(message, "exit") == 0) {
break;
}
else {
sprintf(buffer, "%s\n", message);
send(sockfd, buffer, sizeof(buffer), 0);
}
bzero(message, LENGTH);
bzero(buffer, LENGTH + 32);
}
catch_ctrl_c_and_exit(2);
}
void recv_msg_handler() {
while (1) {
int n;
FILE *fp;
char buff[1024],*ptr=buff;
int bytes=0,bytes_received;
int file_size;
recv(sockfd, buff, CHUNK_SIZE, 0);
file_size = atoi(buff);
str_trim_lf(buff, sizeof(buff));
printf("%s \n",buff);
str_overwrite_stdout();
}
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
signal(SIGINT, catch_ctrl_c_and_exit);
struct sockaddr_in server_addr;
/* Socket settings */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_port = htons(port);
// Connect to Server
int err = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (err == -1) {
printf("ERROR: connect\n");
return EXIT_FAILURE;
}
char exit_client[] = "exit_client";
char buff[MAX];
bzero(buff, sizeof(buff));
recv(sockfd, buff, 1024, 0);
if((strcmp(buff, exit_client) == 0)){
printf("limit exceeded , closing the client \n");
close(sockfd);
return EXIT_SUCCESS;
}
else{
printf("client accepted by the server and limit not exceeded \n");
}
printf("=== WELCOME TO THE CHATROOM ===\n");
pthread_t send_msg_thread;
if(pthread_create(&send_msg_thread, NULL, (void *) send_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
pthread_t recv_msg_thread;
if(pthread_create(&recv_msg_thread, NULL, (void *) recv_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
while (1){
if(flag){
printf("\nBye\n");
break;
}
}
close(sockfd);
return EXIT_SUCCESS;
}
Server side:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <signal.h>
#define MAX_CLIENTS 3
#define BUFFER_SZ 2048
#define SIZE 1024
#define CHUNK_SIZE 512
static _Atomic unsigned int cli_count = 0;
static int uid = 10;
/* Client structure */
typedef struct{
struct sockaddr_in address;
int sockfd;
int uid;
char name[32];
} client_t;
client_t *clients[MAX_CLIENTS];
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
void str_overwrite_stdout() {
printf("\r%s", "> ");
fflush(stdout);
}
void print_client_addr(struct sockaddr_in addr){
printf("%d.%d.%d.%d",
addr.sin_addr.s_addr & 0xff,
(addr.sin_addr.s_addr & 0xff00) >> 8,
(addr.sin_addr.s_addr & 0xff0000) >> 16,
(addr.sin_addr.s_addr & 0xff000000) >> 24);
}
/* Add clients to queue */
void queue_add(client_t *cl){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(!clients[i]){
clients[i] = cl;
break;
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Remove clients to queue */
void queue_remove(int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid == uid){
clients[i] = NULL;
break;
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
void send_file(int sockfd){
int n;
char data[SIZE] = {0};
FILE *fp = fopen("clientid_timestamp.txt", "r");
if (fp == NULL){
printf("Error opening file!\n");
exit(1);
}
char file_data[CHUNK_SIZE];
size_t nbytes = 0;
while ( (nbytes = fread(data, sizeof(char), CHUNK_SIZE,fp)) > 0){
if (send(sockfd, data, nbytes, 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
}
}
/* Send message to all clients except sender */
void send_message(char *s, int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i<MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid != uid){
printf("MESSAGE SENT TO %s:%d \n",inet_ntoa(clients[i]->address.sin_addr),ntohs(clients[i]->address.sin_port));
send_file(clients[i]->sockfd);
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Handle all communication with the client */
void *handle_client(void *arg){
char buff_out[BUFFER_SZ];
char name[32];
int leave_flag = 0;
cli_count++;
client_t *cli = (client_t *)arg;
// Name
bzero(buff_out, BUFFER_SZ);
while(1){
if (leave_flag) {
break;
}
int receive = recv(cli->sockfd, buff_out, BUFFER_SZ, 0);
if (receive > 0){
if(strlen(buff_out) > 0){
FILE *f = fopen("clientid_timestamp.txt", "w");
if (f == NULL){
printf("Error opening file!\n");
exit(1);
}
/* print some text */
fprintf(f, "%s", buff_out);
fclose(f);
send_message(buff_out, cli->uid);
printf("\n");
}
}
else {
printf("ERROR: -1\n");
leave_flag = 1;
}
}
/* Delete client from queue and yield thread */
close(cli->sockfd);
queue_remove(cli->uid);
free(cli);
cli_count--;
pthread_detach(pthread_self());
return NULL;
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
int option = 1;
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
pthread_t tid;
/* Socket settings */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(ip);
serv_addr.sin_port = htons(port);
/* Ignore pipe signals */
signal(SIGPIPE, SIG_IGN);
if(setsockopt(listenfd, SOL_SOCKET,(SO_REUSEPORT | SO_REUSEADDR),(char*)&option,sizeof(option)) < 0){
perror("ERROR: setsockopt failed");
return EXIT_FAILURE;
}
/* Bind */
if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR: Socket binding failed");
return EXIT_FAILURE;
}
/* Listen */
if (listen(listenfd, 10) < 0) {
perror("ERROR: Socket listening failed");
return EXIT_FAILURE;
}
printf("=== WELCOME TO THE CHATROOM ===\n");
char exit[] = "exit_client";
char accepted[] = "accept_client";
while(1){
socklen_t clilen = sizeof(cli_addr);
connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);
/* Check if max clients is reached */
if((cli_count) == MAX_CLIENTS){
printf("Max clients reached. Rejected: ");
print_client_addr(cli_addr);
printf(":%d\n", cli_addr.sin_port);
send(connfd, exit, sizeof(exit), 0);
close(connfd);
continue;
}
else{
send(connfd, accepted, sizeof(accepted), 0);
client_t *cli = (client_t *)malloc(sizeof(client_t));
cli->address = cli_addr;
cli->sockfd = connfd;
cli->uid = uid++;
printf("Client Connected : ");
printf("%s:%d \n",inet_ntoa(cli->address.sin_addr),ntohs(cli->address.sin_port));
/* Add client to the queue and fork thread */
queue_add(cli);
pthread_create(&tid, NULL, &handle_client, (void*)cli);
/* Reduce CPU usage */
sleep(1);
}
/* Client settings */
}
return EXIT_SUCCESS;
}
Server side:
send_file(clients[i]->uid); ought to be send_file(clients[i]->sockfd);
fclose(f); should probably go before send_message(buff_out, cli->uid);
Client side:
printf("%s\n",ptr); (before if(bytes_received==-1)) ought to be removed
There are other inconsistencies, unused variables, etc. This reivew is very limited.
I am writing a program that receives data from the UDP process and delivers it to the next process through shared memory. However, I used semaphores and threads because I didn't want to use usleep(). When you receive data from UDP through the thread, you will be asked to queue the data and the main thread will write the data in shared memory through dequeue. However, data losses still occur, and I wonder why this occurs. If you still use usleep(), the data losses disappears.
I also used mutex for enqueue and dequeue. These symptoms are okay when transmitting small data, but when transmitting text larger than the buffer size, there is an omission in data transmission.
rcv from UDP&write on shared memory
Queuqe
#include "header.h"
#define PORTNUM 8887
//Queue//
typedef struct Node {
char *data;
struct Node* next;
}Node;
typedef struct Queue {
Node* front;
Node* rear;
int count;
}Queue;
void initQueue(Queue* queue) {
queue->front = queue->rear = NULL;
queue->count = 0;
}
int isEmpty(Queue* queue) {
return queue->count == 0;
}
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void enqueue(Queue* queue, char* ddata) {
pthread_mutex_lock(&mutex);
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data =(char *)malloc(strlen(ddata) + 1);
memset(newNode->data, 0x00, strlen(ddata) + 1);
strcpy(newNode->data, ddata);
newNode->next = NULL;
if (isEmpty(queue))
queue->front = newNode;
else
queue->rear->next = newNode;
queue->rear = newNode;
queue->count++;
pthread_mutex_unlock(&mutex);
}
char* dequeue(Queue* queue) {
pthread_mutex_lock(&mutex);
static char data[MAX_BUF_SIZE + 1];
memset(data, 0x00, MAX_BUF_SIZE + 1);
Node* ptr;
if (isEmpty(queue)) {
printf("Error : Queue is empty\n");
return 0;
}
ptr = queue->front;
strcpy(data, ptr->data);
queue->front = ptr->next;
free(ptr);
queue->count--;
pthread_mutex_unlock(&mutex);
return data;
}
semaphore and thread
//semaphore union//
union semun{
int val;
struct semid_dsi* sem;
unsigned short int* array;
};
//thread//
typedef struct Trcv{
int sd;
Queue squeue;
}Trcv;
void *rcv(void *p){
char buf[MAX_BUF_SIZE+1];
Trcv *pp = (Trcv *)p;
struct sockaddr_in serv;
int len = sizeof(serv);
while(1){
memset(buf, 0x00, MAX_BUF_SIZE+1);
if((recvfrom(pp->sd, buf, MAX_BUF_SIZE, 0, (struct sockaddr *)&serv, (socklen_t *)&len)) == -1){
perror("recvfrom");
exit(1);
}
enqueue(&pp->squeue, buf);
}
}
main
int main(){
Queue queue;
initQueue(&queue);
Trcv trcv;
int shm_id;
int sem_id;
char text[MAX_BUF_SIZE+1];
int sd;
struct sockaddr_in serv;
int bsize;
int cnt = 0;
int total = 0;
if((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
perror("socket");
exit(1);
}
memset((char *)&serv, '\0', sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
serv.sin_port = htons(PORTNUM);
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &bsize, sizeof(bsize));
if(bind(sd, (struct sockaddr *)&serv, sizeof(serv)) == -1){
perror("bind");
exit(1);
}
//shared memory//
key_t shm_key;
void *buf;
//semaphore//
key_t sem_key;
union semun sem_u;
struct sembuf mysem_open = {0, -1, SEM_UNDO};
struct sembuf mysem_close = {0, 1, SEM_UNDO};
shm_key = 1123;
if((shm_id = shmget(shm_key, MAX_BUF_SIZE+1, IPC_CREAT|0666)) == -1){
perror("shmget");
exit(1);
}
if((buf = (void *)shmat(shm_id, NULL, 0)) == (void *) -1){
perror("SM shmat");
exit(1);
}
//semaphore//
sem_key = 1234;
if((sem_id = semget(sem_key, 1, IPC_CREAT|0666)) == -1){
printf("semapore segment already exist\n");
exit(1);
}
else
printf("new semapore segment created\n");
//semaphore value setting//
sem_u.val = 1;
semctl(sem_id, 0, SETVAL, sem_u);
/////////////////
pthread_t pt_rcv;
trcv.sd = sd;
trcv.squeue = queue;
pthread_create(&pt_rcv, NULL, rcv, (void *)&trcv);
while(1){
if(!isEmpty(&trcv.squeue)){
if(semop(sem_id, &mysem_open, 1) == -1){//open
perror("semop");
exit(1);
}
memset(text, 0x00, MAX_BUF_SIZE+1);
strncpy(text, dequeue(&trcv.squeue), MAX_BUF_SIZE);
printf("%s\n",text);
cnt = strlen(text);
total += cnt;
printf("\n======================\n");
printf("size : %d\n",cnt);
printf("total : %d\n",total);
printf("======================\n\n");
memcpy(buf, text, MAX_BUF_SIZE);
semop(sem_id, &mysem_close, 1);//close
}
//usleep(30000);
}
shmctl(shm_id, IPC_RMID, NULL);
shmdt(buf);
close(sd);
return 0;
}
read from shared memory
#include "header.h"
#include <log.h>
int main(){
//shared memroy//
key_t shm_key;
void *buf;//void *shmaddr
char text[MAX_BUF_SIZE+1];
//semapore//
key_t sem_key;
struct sembuf mysem_open = {0, -1, SEM_UNDO};//open sem
struct sembuf mysem_close = {0, 1, SEM_UNDO};//close sem
int shm_id;a
int sem_id;
int cnt = 0;
int total = 0;
if(access("result.txt", F_OK) == 0){
unlink("result.txt");
printf("result file unlinked\n");
}
I'm going to print out the text I received as a file.
FILE *fp = NULL;
LogSetup();
shm_key = 1123;
if((shm_id = shmget(shm_key, 0, 0)) == -1){
LOG_ERROR("shmget ERR");
perror("shmget");
exit(1);
}
else
LOG_TRACE("shmget id : %d",shm_id);
if((buf = (void *)shmat(shm_id, NULL, 0))==(void *)-1){
LOG_FATAL("shmat ERR");
perror("shmat");
exit(1);
}
else
LOG_DEBUG("BUF");
sem_key = 1234;
LOG_TRACE("TRACE");
if((sem_id = semget(sem_key, 1, IPC_CREAT|0666)) == -1){
LOG_ERROR("segmet ERR");
printf("Semapore segment alreday exist\n");
exit(1);
}
else{
printf("new semapore segment created\n");
LOG_ERROR("semget id : %d",sem_id);
}
while(1){
if((semop(sem_id, &mysem_open, 1)) == -1){//open sema
LOG_ERROR("semaphore open ERR");
perror("semop");
exit(1);
}
memset(text, 0x00, MAX_BUF_SIZE+1);
strncpy(text,(char *)buf, MAX_BUF_SIZE);
if(strncmp(text,"",MAX_BUF_SIZE) != 0){
fp = fopen("result.txt","a");
printf("%s\n",text);
fwrite(text, 1, strlen(text), fp);
fclose(fp);
cnt = strlen(text);
total += cnt;
printf("\n======================\n");
printf("size : %d\n",cnt);
printf("total : %d\n",total);
printf("======================\n\n");
LOG_INFO("Recv text : %s",text);
LOG_INFO("total size : %d",total);
}
memset(buf, 0x00, MAX_BUF_SIZE+1);
if(semop(sem_id, &mysem_close,1) == -1){
LOG_ERROR("semaphore close ERR");
perror("semop");
exit(1);
}
}
shmctl(shm_id, IPC_RMID, NULL);
shmdt(buf);
return 0;
}
I am using VS2010. Is it possible to make SOCKET global so I can call this socket from all .c files in same project? Is possible, how to do it? If not possible, why not? Below are my codes:
global is where I am creating my global socket. I am using it in main.c and send.c.
global.h
extern SOCKET s;
typedef struct
{
int x;
double y;
char z[32];
}Person;
main.c
#include "stdafx.h"
#include "send.f"
SOCKET s;
void printPerson(Person *p)
{
printf("p.x: %d\n", p->x);
printf("p.y: %f\n", p->y);
printf("p.z: %s\n", p->z);
}
void establishConnection()
{
//extern SOCKET s;
struct sockaddr_in server;
//struct addrinfo hints;
//char *message, server_reply[2000];
//int recv_size;
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
}
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(200);
if(connect(s, (struct sockaddr *)&server, sizeof(server)) < 0)
{
puts("Connect error");
Sleep(1000);
puts("Retrying");
establishConnection();
}
else
puts("Server Connected\n");
}
int main()
{
char *name;
int a;
WSADATA wsa;
puts("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
puts("Initialized.");
establishConnection();
{
Person p1;
recieveData(&p1);
printPerson(&p1);
printf("\n");
}
{
Person p2;
p2.x = 22;
p2.y = 2.2;
name = "C Plus Plus";
strcpy(p2.z, name);
printPerson(&p2);
sendData(&p2);
}
scanf("%d", &a);
return 0;
}
send.f
void sendData(Person*);
void recieveData(Person*);
send.c
#include "stdafx.h"
void recieveData(Person* p)
{
//extern SOCKET s;
char bufLen[8];
int length, XX;
double YY;
char *msg, *token;
char *ZZ;
if(recv(s, bufLen, 8, 0) < 0)
{
puts("Receive failed");
return;
}
length = atoi(bufLen);
msg = malloc(length + 1);
memset(msg, 0, length + 1);
if (recv(s, msg, length, 0) < 0)
{
puts("Receive failed");
return;
}
printf("Before first token: %s\n", msg);
token = strtok(msg, ";");
printf("After first token: %s\n", token);
XX = atoi(token);
printf("XX: %d\n", XX);
p->x = atoi(token);
token = strtok(NULL, ";");
printf("After second token: %s\n", token);
YY = atof(token);
printf("YY: %f\n", YY);
p->y = atof(token);
token = strtok(NULL, ";");
printf("After third token: %s\n", token);
ZZ = malloc(strlen(token));
memset(ZZ, 0, 32);
strcpy(ZZ, token);
printf("ZZ: %s\n", ZZ);
memset(p->z, 0, 32);
strcpy(p->z, token);
free(msg);
puts("Received!");
}
void sendData(Person* p)
{
//extern SOCKET s;
char msg[2000], clen[9];
int len;
//char *msg;
//msg = malloc(2000);
sprintf(msg, "%d;%f;%s", p->x, p->y, p->z);
len = strlen(msg);
sprintf(clen, "%08d", len);
if (send(s, clen, 8, 0) < 0)
{
puts("Send failed");
return;
}
if (send(s, msg, len, 0) < 0)
{
puts("Send failed");
return;
}
puts("Sent!\n");
}
stdafx.h
#pragma once
#include <tchar.h>
#include "global.h"
#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
Your global.h is trying to use SOCKET, which is undeclared at that point. You're missing an #include (probably <winsock2.h>) in global.h.
My OS is linux.I program socket in C.I'm a newwork-programming newbie. Today, I want the single client to write the message to the multiple servers, so I open the two terminals to represent the two servers.But the first server is right, and the second server is still waiting the message from the client.At the same time, the client is over.Therefore, the first server read the message which the client send to the server.I have no idea that what happened.
the client.c:
#include <stdio.h>
#include <string.h> //strlen
#include <sys/socket.h>
#include <arpa/inet.h> //inet_addr
#include <netdb.h> //hostent
#include <pthread.h>
#include <ctype.h>
#include <stdint.h>
#include <limits.h>
#include <assert.h>
#include <sys/time.h>
#include <pthread.h>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>
#define NAMEMAX 4096
int socket_desc;
int packet_num;
struct timeval timeout;
int main(int argc , char *argv[]){
sscanf(argv[2], "%d", &packet_num);
//printf("packet_num = %d\n", packet_num);
timeout.tv_sec = 0L;
sscanf(argv[4], "%ld", &timeout.tv_usec);
//printf("timeout.tv_sec = %ld, timeout.tv_usec = %ld\n", timeout.tv_sec, timeout.tv_usec);
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
//printf("socket_desc = %d\n", socket_desc);
int j = 5;
int t;
int isip = 1;
while(j < argc){
//int new_socket
struct sockaddr_in server;
//server_object server;
char hostname[NAMEMAX] = {0};
uint16_t portnum = 0;
int meet = 0;
int k;
for(k = 0; k < strlen(argv[j]); k++){
if(argv[j][k] == ':'){
//portnum = argv[j]+(k+1);
meet = 1;
t = (k+1);
continue;
}
if(meet == 0){
hostname[k] = argv[j][k];
if(isdigit(argv[j][k]) || argv[j][k] == '.'){
isip = 1;
}
else{
isip = 0;
}
}
if(meet == 1){
portnum = portnum*10 + (argv[j][k] - '0');
}
}
char ip[100];
memset(ip, 0, sizeof(ip));
struct hostent *he;
struct in_addr **addr_list;
int i;
struct in_addr hipaddr;
if(isip){
inet_aton(hostname, &hipaddr);
he = gethostbyaddr(&hipaddr, 4, AF_INET);
}
else{
he = gethostbyname( hostname );
}
//Cast the h_addr_list to in_addr , since h_addr_list also has the ip address in long format only
addr_list = (struct in_addr **) he->h_addr_list;
for(i = 0; addr_list[i] != NULL; i++){
//Return the first one;
strcpy(ip , inet_ntoa(*addr_list[i]) );
}
//printf("%s resolved to : %s\n" , hostname , ip);
//strcpy(server.server_ip, ip);
//printf("port = %u\n", portnum);
//server.server_portportnum;
server.sin_addr.s_addr = inet_addr(ip);
server.sin_family = AF_INET;
server.sin_port = htons(portnum);
//thread start
//pthread_t ntid;
//pthread_create(&ntid, NULL, request, &server);
struct timeval start;
struct timeval end;
struct timeval thistimeout = timeout;
int num = 0;
//Connect to remote server
int test_con = connect(socket_desc , (struct sockaddr *)&server , sizeof(server));
//printf("test_con = %d\n", test_con);
//puts("Connected\n");
//Send some data
//while-loop begin
//int overtime = 0;
while(((num < packet_num && packet_num != 0) || (packet_num == 0)) && thistimeout.tv_usec >= 0){
char msg[200];
memset(msg, 0, sizeof(msg));
//strcpy(msg, "GET / HTTP/1.1\r\n\r\n");
sprintf(msg, "%d", num);
long diff;
gettimeofday(&start,NULL);
printf("msg = %s\n", msg);
ssize_t write_s;
write_s = write(socket_desc, msg, sizeof(msg));
printf("write_s = %ld\n", write_s);
//printf("write_s = %ld\n", write_s);
//printf("msg = %s\n", msg);
//puts("write failed");
assert(num <= INT_MAX);
//Receive a reply from the server
char buf[2000];
//printf("readbef\n");
ssize_t read_s;
read_s = read(socket_desc, buf, sizeof(buf));
printf("read_s = %ld\n", read_s);
//printf("readafter\n");
//printf("buf = %s\n", buf);
gettimeofday(&end,NULL);
diff = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec;
thistimeout.tv_usec -= diff;
//printf("thistimeout.tv_usec = %ld\n", thistimeout.tv_usec);
//printf("thedifference is %ldmsec\n",diff);
//printf("buf = %s\n", buf);
//puts("Reply received\n");
printf("recv from %s:%u, seq = %s, RTT = %ld msec\n", ip, portnum, buf, diff);
fflush(stdout);
num++;
}
if(thistimeout.tv_usec < 0){
printf("timeout when connect to %s:%u, seq = %d\n", ip, portnum, num);
fflush(stdout);
}
close(socket_desc);
sleep(1);
j++;
}
return 0;
}
the server.c:
#include <stdio.h>
#include <string.h> //strlen
#include <stdlib.h> //strlen
#include <sys/socket.h>
#include <arpa/inet.h> //inet_addr
#include <unistd.h> //write
#include <pthread.h> //for threading , link with lpthread
#include <netinet/in.h>
#include <sys/time.h>
int sv_socket_desc;
int main(int argc , char *argv[]){
int new_socket , c;
struct sockaddr_in server , client;
//Create socket
sv_socket_desc = socket(AF_INET , SOCK_STREAM , 0);
//printf("sv_socket_desc = %d\n", sv_socket_desc);
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
uint16_t portnum;
sscanf(argv[1], "%hu", &portnum);
server.sin_port = htons(portnum);
//server.sin_port = htons( 8888 );
//Bind
bind(sv_socket_desc,(struct sockaddr *)&server , sizeof(server));
//Listen
listen(sv_socket_desc , 3);
//Accept and incoming connection
c = sizeof(struct sockaddr_in);
while(1){
new_socket = accept(sv_socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
printf("new_socket = %d\n", new_socket);
//puts("Connection accepted");
//Reply to the client
struct sockaddr_in newclient;
//start thread
ssize_t read_size = 0L;
ssize_t write_size = 0L;
char client_message[200];
memset(client_message, 0, sizeof(client_message));
unsigned short int client_port_num = ntohs(newclient.sin_port);
char client_addr[2000];
//inet_ntop(AF_INET6, &(newclient.sin_addr.s_addr), client_addr, INET6_ADDRSTRLEN);
printf("00\n");
char *clientIP = inet_ntoa(client.sin_addr);
while(read_size >= 0){
//(read_size = read(sv_socket_desc, client_message, sizeof(client_message))) >= 0
//printf("readbef\n");
//printf();
read_size = read(new_socket, client_message, sizeof(client_message));
printf("read_size = %ld\n", read_size);
//fflush(stdin);
//printf("read_size = %ld\n", read_size);
//printf("client_message = %s\n", client_message);
//fflush(stdout);
write_size = write(new_socket, client_message, sizeof(client_message));
if(read_size){
printf("recv from %s:%hu, seq = %s\n", clientIP, client_port_num, client_message);
}
//printf("recv from %s:%hu, seq = %s\n", client_addr, client_port_num, client_message);
memset(client_message, 0, sizeof(client_message));
fflush(stdout);
}
printf("01\n");
fflush(stdout);
//Free the socket pointer
close(new_socket);
sleep(1);
}
return 0;
}
My OS is linux. I program socket in C. I tested the client and the server at the same time. Both of them are on my localhost. However, when the client write the message to the server, but the server cannot read the message from the client. I have no idea that what wrong it is. I'm sure that the client and the server connect to each other. My main purpose is that the client write the message, whose content is the sequence number, to the server, and then the server can reply the message to the client back.
I use pthread to make the client can connect to the multiple servers.
the part function code from the client.c:
#include<stdio.h>
#include<string.h> //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<netdb.h> //hostent
#include <pthread.h>
#include <ctype.h>
#include <stdint.h>
#include <limits.h>
#include <assert.h>
#include <sys/time.h>
#include <pthread.h>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>
#define NAMEMAX 4096
int socket_desc;
int packet_num;
struct timeval timeout;
typedef struct server_object{
char server_ip[100];
uint16_t server_port;
struct sockaddr_in server_about;
}server_object;
void* request(void* server_func){
server_object* server_pointer = (server_object*) server_func;
struct timeval start;
struct timeval end;
struct timeval thistimeout;
int num = 0;
//Connect to remote server
int test_con = connect(socket_desc , (struct sockaddr *)&(server_pointer->server_about) , sizeof(server_pointer->server_about));
printf("test_con = %d\n", test_con);
fd_set read_fd2;
FD_ZERO(&read_fd2);
FD_SET(socket_desc, &read_fd2);
int fdmax2;
fdmax2 = socket_desc;
/*int ret2 = select(fdmax2+1, &read_fd2, NULL, NULL, &thistimeout);
if(ret2 == 0){
printf("00\n");
printf("timeout when connect to %s:%u, seq = %d\n", server_pointer->server_ip, server_pointer->server_port, num);
fflush(stdout);
return 0;
}*/
//puts("Connected\n");
//Send some data
//while-loop begin
int overtime = 0;
while((num < packet_num && packet_num != 0) || (packet_num == 0)){
char msg[200];
memset(msg, 0, sizeof(msg));
//strcpy(msg, "GET / HTTP/1.1\r\n\r\n");
sprintf(msg, "%d", num);
unsigned long diff;
gettimeofday(&start,NULL);
printf("msg = %s\n", msg);
ssize_t write_s;
write_s = write(socket_desc, msg, sizeof(msg));
printf("write_s = %ld\n", write_s);
printf("msg = %s\n", msg);
//puts("write failed");
assert(num <= INT_MAX);
//puts("Data Send\n");
fd_set read_fd;
FD_ZERO(&read_fd);
FD_SET(socket_desc, &read_fd);
int fdmax;
fdmax = socket_desc;
//int ret = select(fdmax+1, &read_fd, NULL, NULL, &thistimeout);
//if(ret == 0){
// overtime = 1;
// break;
//}
//Receive a reply from the server
char buf[2000];
printf("readbef\n");
read(socket_desc, buf, sizeof(buf));
printf("readafter\n");
printf("buf = %s\n", buf);
gettimeofday(&end,NULL);
diff = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec;
thistimeout.tv_usec -= diff;
//printf("thedifference is %ldmsec\n",diff);
//printf("buf = %s\n", buf);
//puts("Reply received\n");
printf("recv from %s:%u, seq = %d, RTT = %lu msec\n", server_pointer->server_ip, server_pointer->server_port, num, diff);
fflush(stdout);
num++;
}
if(overtime == 1){
printf("timeout when connect to %s:%u, seq = %d\n", server_pointer->server_ip, server_pointer->server_port, num);
fflush(stdout);
}
return 0;
}
int main(int argc , char *argv[]){
sscanf(argv[1], "%d", &packet_num);
//printf("packet_num = %d\n", packet_num);
timeout.tv_sec = 0;
sscanf(argv[2], "%lu", &timeout.tv_usec);
//printf("timeout.tv_sec = %lu, timeout.tv_usec = %lu\n", timeout.tv_sec, timeout.tv_usec);
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
printf("socket_desc = %d\n", socket_desc);
int j = 3;
int t;
int isip = 1;
while(j < argc){
//int new_socket
//struct sockaddr_in server;
server_object server;
char hostname[NAMEMAX] = {0};
uint16_t portnum = 0;
int meet = 0;
int k;
for(k = 0; k < strlen(argv[j]); k++){
if(argv[j][k] == ':'){
//portnum = argv[j]+(k+1);
meet = 1;
t = (k+1);
continue;
}
if(meet == 0){
hostname[k] = argv[j][k];
if(isdigit(argv[j][k]) || argv[j][k] == '.'){
isip = 1;
}
else{
isip = 0;
}
}
if(meet == 1){
portnum = portnum*10 + (argv[j][k] - '0');
}
}
char ip[100];
memset(ip, 0, sizeof(ip));
struct hostent *he;
struct in_addr **addr_list;
int i;
struct in_addr hipaddr;
if(isip){
inet_aton(hostname, &hipaddr);
he = gethostbyaddr(&hipaddr, 4, AF_INET);
}
else{
he = gethostbyname( hostname );
}
//Cast the h_addr_list to in_addr , since h_addr_list also has the ip address in long format only
addr_list = (struct in_addr **) he->h_addr_list;
for(i = 0; addr_list[i] != NULL; i++){
//Return the first one;
strcpy(ip , inet_ntoa(*addr_list[i]) );
}
//printf("%s resolved to : %s\n" , hostname , ip);
strcpy(server.server_ip, ip);
//printf("port = %u\n", portnum);
server.server_port = portnum;
server.server_about.sin_addr.s_addr = inet_addr(ip);
server.server_about.sin_family = AF_INET;
server.server_about.sin_port = htons(portnum);
//thread start
pthread_t ntid;
pthread_create(&ntid, NULL, request, &server);
sleep(10);
j++;
}
return 0;
}
I use pthread to make the server can accept the multiple clients.
the part function code from the server.c:
#include <stdio.h>
#include <string.h> //strlen
#include <stdlib.h> //strlen
#include <sys/socket.h>
#include <arpa/inet.h> //inet_addr
#include <unistd.h> //write
#include <pthread.h> //for threading , link with lpthread
#include <netinet/in.h>
#include <sys/time.h>
int sv_socket_desc;
typedef struct client_object{
struct sockaddr_in client_about;
int client_fsd;
}client_object;
void *connection_handler(void *);
int main(int argc , char *argv[]){
int new_socket , c;
struct sockaddr_in server , client;
//Create socket
sv_socket_desc = socket(AF_INET , SOCK_STREAM , 0);
printf("sv_socket_desc = %d\n", sv_socket_desc);
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
//uint16_t portnum;
//sscanf(argv[1], "%hu", &portnum);
//server.sin_port = htons(portnum);
server.sin_port = htons( 8888 );
//Bind
bind(sv_socket_desc,(struct sockaddr *)&server , sizeof(server));
//Listen
listen(sv_socket_desc , 3);
//Accept and incoming connection
c = sizeof(struct sockaddr_in);
while( (new_socket = accept(sv_socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) ){
//puts("Connection accepted");
//Reply to the client
client_object* new_sock;
client_object newclient;
newclient.client_about = client;
newclient.client_fsd = new_socket;
//start thread
fflush(stdout);
pthread_t sniffer_thread;
new_sock = (client_object*)malloc(sizeof(client_object));
*new_sock = newclient;
fflush(stdout);
pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock);
sleep(10);
//thread over
//Now join the thread , so that we dont terminate before the thread
pthread_join( sniffer_thread , NULL);
//puts("Handler assigned");
}
return 0;
}
/*
* This will handle connection for each client
* */
void *connection_handler(void *socket_desc){
//Get the socket descriptor
client_object newclient = *(client_object*) socket_desc;
ssize_t read_size;
char client_message[200];
memset(client_message, 0, sizeof(client_message));
unsigned short int client_port_num = ntohs(newclient.client_about.sin_port);
char client_addr[2000];
inet_ntop(AF_INET6, &(newclient.client_about.sin_addr.s_addr), client_addr, INET6_ADDRSTRLEN);
/*fflush(stdout);
read_size = read(sv_socket_desc, client_message, sizeof(client_message));
printf("client_msg = %s\n", client_message);
printf("read_size = %ld\n", read_size);
fflush(stdout);*/
while(1){
//(read_size = read(sv_socket_desc, client_message, sizeof(client_message))) >= 0
//printf("readbef\n");
read_size = read(sv_socket_desc, client_message, sizeof(client_message));
printf("read_size = %ld\n", read_size);
printf("client_message = %s\n", client_message);
fflush(stdout);
read_size = write(sv_socket_desc, client_message, sizeof(client_message));
int n;
sscanf(client_message, "%d", &n);
printf("recv from %s:%hu, seq = %d\n", client_addr, client_port_num, n);
fflush(stdout);
}
fflush(stdout);
//Free the socket pointer
free(socket_desc);
return 0;
}
#Eddie Lin,
you passed wrong fd in connection_handler() in server.c.
Do replace sv_socket_desc with newclient.client_fsd because accept return FD which is used for communication purpose, sv_socket_desc is a socket for listen new connection.
while(1){
//printf("readbef\n");
read_size = read(newclient.client_fsd, client_message, sizeof(client_message));
printf("read_size = %ld\n", read_size);
printf("client_message = %s\n", client_message);
fflush(stdout);
read_size = write(newclient.client_fsd, client_message, sizeof(client_message));
int n;
sscanf(client_message, "%d", &n);
printf("recv from %s:%hu, seq = %d\n", client_addr, client_port_num, n);
fflush(stdout);
}