How can i print current time when string is "Time" in C? - c

I am working on a c program that sends the message and gets the message back from server,but i want to send the time to EchoClient if the string is "time".
How can i do it?
I have tried to work with some codes but they seem too complicated for my knowledge.Does anybody know how to do it?
EchoClient.c
#include "nethelp.h"
int main(int argc, char **argv)
{
int clientfd, port;
char *host, buf[MAXLINE];
int n;
if (argc != 3) {
fprintf(stderr, "usage: %s <host> <port>\n", argv[0]);
exit(0);
}
host = argv[1];
port = atoi(argv[2]);
clientfd = open_clientfd(host, port);
while (fgets(buf, MAXLINE, stdin) != NULL) {
write(clientfd, buf, strlen(buf));
n = readline(clientfd, buf, MAXLINE);
write(1, buf, n);
}
close(clientfd);
exit(0);
}
EchoServer.c
#include "nethelp.h"
void echo(int connfd);
void *thread(void *vargp);
int main(int argc, char **argv)
{
int listenfd, *connfdp, port, clientlen=sizeof(struct sockaddr_in);
struct sockaddr_in clientaddr;
pthread_t tid;
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(0);
}
port = atoi(argv[1]);
listenfd = open_listenfd(port);
while (1) {
connfdp = malloc(sizeof(int));
*connfdp = accept(listenfd, (struct sockaddr*)&clientaddr, &clientlen);
pthread_create(&tid, NULL, thread, connfdp);
}
}
void * thread(void * vargp)
{
int connfd = *((int *)vargp);
pthread_detach(pthread_self());
free(vargp);
echo(connfd);
close(connfd);
return NULL;
}
void echo(int connfd)
{
size_t n;
char buf[MAXLINE];
while((n = readline(connfd, buf, MAXLINE)) != 0) {
printf("server received %d bytes\n", n);
write(connfd, buf, n);
}
}

To send the current time as text,
if (strcmp(buf, "time")== 0) {
time_t now;
time(&now); // Get the current time
if (now == -1) Handle_Error();
struct tm *tm;
tm = gmtime(&now); // Convert to a time struct (YMD HMS etc.) as if Universal time
if (tm == NULL) Handle_Error();
char buf[100];
// See strftime and ISO 8601 for format details
// Convert from a time struct to a string
if (strftime(buf, sizeof buf, "%FT%T") == 0) Handle_Error();
send(buf);
}

Related

Sending files from a client to a server and then reading the file in another client using sockets in C

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.

Writing to server returns nothing

the below is a snippet of a chatclient called Marvin, where, given someone saying something like "Hey Marvin, 1+1", the program will send onto the server "Hey user, 2". The issue is, even though the output can print properly client sized, when I attempt to send it to server using write(), the server just gets "Marvin:"
Any ideas on why my write() isn't working? I highlighted the areas where I used write but they're in the second function, halfway through. There are a lot of helper functions, so I cut them down and explained what they usually do.
static int sockfd;
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr, "usage: %s hostname [port number] ...\n", argv[0]);
return(1);
}
//INITIALIZERS
//int sockfd;
fd_set master;
char buf[500];
struct hostent *hp;
struct sockaddr_in peer;
char *name = malloc(MAXHANDLE);
char *todo = malloc(MAXMESSAGE); /*
extern void reply(char *buf, char *name);
extern char *myreadline(struct client *p);
struct client *p = malloc(sizeof(struct client));
extern int tracer(char *str, int start, int len);
extern int choice(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
*/
//HOST
if ((hp = gethostbyname(argv[1])) == NULL) {
fprintf(stderr, "%s: no such host\n", argv[1]);
return(1);
}
if (hp->h_addr_list[0] == NULL || hp->h_addrtype != AF_INET) {
fprintf(stderr, "%s: not an internet protocol host name\n", argv[1]);
return(1);
}
//SOCKET
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}
memset(&peer, '\0', sizeof peer);
peer.sin_family = AF_INET;
peer.sin_addr.s_addr = INADDR_ANY;
//PORT
if (argc > 2) {
if (!(port = atoi(argv[2])) == 0) {
peer.sin_port = htons(port);
} else {
fprintf(stderr, "%s: port number must be a positive integer\n", argv[0]);
return(1);
}
} else {
peer.sin_port = htons(1234);
}
//SOCKET
peer.sin_addr = *((struct in_addr*)(hp->h_addr));
if (connect(sockfd, (struct sockaddr *)&peer, sizeof(peer)) == -1) {
perror("connect");
close(sockfd);
exit(1);
}
FD_ZERO(&master);
FD_SET(STDIN_FILENO, &master);
FD_SET(sockfd, &master);
fd_set fds;
//BANNER HANDLE
//FILLS *p WITH INFORMATION of server
//*p = addclient(sockfd);
char *buff = malloc(500);
while (1) {
//READS A LINE
//buff = myreadline(p);
if (buff == NULL)
continue;
if (!strcmp(buff, CHATSVR_ID_STRING)) {
write(sockfd, "Marvin", MAXHANDLE);
break;
} else {
fprintf(stderr, "%s: invalid chatsvr\n", buff);
exit(1);
}
}
//LOOP
while(1) {
fds = master;
//RUNS SELECT WITH ERROR CHECKING
choice(sockfd+1, &fds, NULL, NULL, NULL);
if(FD_ISSET(STDIN_FILENO, &fds)) {
fgets(buf, sizeof buf, stdin);
if (strlen(buf) > 0) {
reply(buf, "Marvin");
}
} else if (FD_ISSET(sockfd, &fds)) {
//name = myreadline(p);
if (name != NULL) {
printf("%s\n", name);
strtok_r(name, ": ", &todo);
//tracer(todo, 0, 1);
reply(todo, name);
}
}
}
return(0);
}
//Given name and command, prints required output
void reply(char *buf, char *name) {
//extern int tracer(char *str, int start, int len);
//extern int tinder(const char *a, const char *b);
char *replied = buf;
if (strlen(buf) > 0) {
if (!tinder(buf, "Hey Marvin,")) {
printf("%s\n", replied);
//ISSUE HERE XXX
write(sockfd, replied, sizeof(replied));
return;
} else {
tracer(buf, 0, 11);
}
struct expr *e = parse(buf);
if (e) {
sprintf(replied, "Marvin: Hey %s, %d\n", name, evalexpr(e));
printf("%s\n", replied);
//ISSUE HERE
write(sockfd, replied, sizeof(replied));
freeexpr(e);
} else {
sprintf(replied, "Marvin: Hey %s, I don't like that.\n[%s]\n", name, errorstatus);
printf("%s\n", replied);
//XXX ISSUE HERE
write(sockfd, replied, sizeof(replied));
}
}
}
From client side, I send:
chatsvr: Welcome to our new participant, Marvin
hi
dsha
^C
Server side, this is what shows up:
chatsvr: Welcome to our new participant, Marvin
Marvin:
Marvin:
Marvin:
chatsvr: Goodbye, Marvin
When it should be:
chatsvr: Welcome to our new participant, Marvin
Marvin: hi
Marvin: dsha
chatsvr: Goodbye, Marvin
//ISSUE HERE XXX
write(sockfd, replied, sizeof(replied));
Here you should use strlen(replied) instead of sizeof.
Make sure make the received string is null terminated before you use it as string.

C: How do you read and unpack a message over a socket?

I am trying to receive an updated message over the socket and unpack the
data. I want to use the update_client function to update the server's
internal representation of the client co-ordinates and respond to the
client with the required value.
I think I should use recv to read the full message (of length UPDATE_CMD_LEN) into buffer.
Then unpack data having message in the following format:
U<id><fields of gpscoords>
Character 'U' (meaning update), followed by ID of the client (unsigned char)
and then the gpscoord structure in network format.
This is a rough idea of how to do it but I don't know how:
[1] Unpack ID
[2] Unpack coordinates with int update_client(unsigned char id, gpscoords *pos
which takes ID and pointer to position struct, returns -1 on error and 0 on success
The server should then respond to client using sendto function and reply
NO_RES on error and SUCC_RES on success.
void do_update(int sockfd, struct sockaddr_in *clientaddr) {
char msg[UPDATE_CMD_LEN];
recv(sockfd, msg, UPDATE_CMD_LEN, flags);
fprintf(stderr, "do_update not implemented!\n");
exit(-1);
}
client.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "gps.h"
#define CMD_LEN 10
#define LINE_LEN NAME_LEN + 15
#define FIREFOX "/usr/bin/firefox"
void make_route_url(char *url, gpscoords *pos, gpscoords *target) {
char pos_sign_n;
char pos_sign_e;
char tar_sign_n;
char tar_sign_e;
pos_sign_n = pos->north ? '+' : '-';
pos_sign_e = pos->east ? '+' : '-';
tar_sign_n = target->north ? '+' : '-';
tar_sign_e = target->east ? '+' : '-';
sprintf(url,
"http://map.project-osrm.org/?z=13&loc=%c%u.%u,%c%u.%u&loc=%c%u.%u,%c%u.%u",
pos_sign_n, pos->lat, pos->lat_frac,
pos_sign_e, pos->lon, pos->lon_frac,
tar_sign_n, target->lat, target->lat_frac,
tar_sign_e, target->lon, target->lon_frac);
}
void show_route(gpscoords *pos, gpscoords *target) {
// char url[75];
fprintf(stderr, "show_route not implemented!\n");
exit(-1);
}
int run_client(char *name, char *serverip) {
char *cmdline;
size_t line_len;
char cmd[11];
gpsinfo info;
gpscoords pos, targetpos;
char targetname[NAME_LEN];
bzero(targetname, NAME_LEN);
bzero(&info, sizeof(info));
bzero(&pos, sizeof(pos));
bzero(&targetpos, sizeof(targetpos));
if (register_client(serverip, name, &info) == -1) {
perror("Error registering client.");
return -1;
}
find_self(&pos);
if (update_position(&info, &pos) == -1) {
printf("Failed to send initial position to server.\n");
exit(-1);
}
for (;;) {
printf("Command: ");
line_len = 0;
cmdline = NULL;
getline(&cmdline, &line_len, stdin);
if (strncmp(cmdline, "update", 3) == 0) {
find_self(&pos);
if (update_position(&info, &pos) == -1) {
printf("Failed to update.\n");
}
} else if (strncmp(cmdline, "find", 3) == 0) {
sscanf(cmdline, "%10s %25s", cmd, targetname);
if (get_position(&info, targetname, &targetpos) == -1) {
printf("Couldn't find target.\n");
} else {
show_route(&pos, &targetpos);
}
} else if (strncmp(cmdline, "quit", 4) == 0) {
free(cmdline);
break;
}
free(cmdline);
}
if (unregister_client(&info) == -1) {
perror("Error unregistering client.");
return -1;
}
return 0;
}
int main(int argc, char **argv) {
if (argc < 2) {
printf("Usage: ./client <client name> <server_ip>\n");
return 0;
}
return run_client(argv[1], argv[2]);
}
socket.c
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "sockets.h"
int create_dg_socket(in_port_t port) {
// Create the socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
printf("create_dg_socket cannot create socket!");
return -1;
}
// Bind the socket port
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
printf("create_dg_socket cannot bind socket!");
close(sockfd);
return -1;
}
return sockfd;
}
int open_dg_socket(char *ipaddr, in_port_t port, struct sockaddr_in *addr) {
// Create the socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
return -1;
}
// Setup
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
addr->sin_addr.s_addr = inet_addr(ipaddr);
return sockfd;
}
int dg_sendrecv(int sockfd,
struct sockaddr_in *addr,
char *message, size_t out_len,
char *response, size_t in_len) {
if (sendto(sockfd, message, out_len, 0, (struct sockaddr *)&addr, sizeof(*addr)) == -1) {
printf("dg_sendrecv cannot send data!");
return -1;
}
int ret = recvfrom(sockfd, response, in_len, 0, NULL, NULL);
if (ret == -1) {
printf("dg_sendrecv cannot read data!");
return -1;
}
return ret;
}
/*
int dg_sendrecv(int sockfd,
struct sockaddr_in *addr,
char *message, size_t out_len,
char *response, size_t in_len) {
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ipaddr);
return dg_sendrecv_addr(sockfd, &addr, message, out_len, response, in_len);
}
*/
server.c
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include "sockets.h"
#include "gps.h"
#include "server.h"
#define NUM_CLIENTS 5
char clients[NUM_CLIENTS][NAME_LEN];
gpscoords coords[NUM_CLIENTS];
void do_register(int sockfd, struct sockaddr_in *clientaddr) {
char msg[REGISTER_CMD_LEN];
char *name;
unsigned char id, i;
if (recv(sockfd, msg, REGISTER_CMD_LEN, 0) == -1) {
perror("Error receiving register command.");
exit(-1);
}
// first byte is server command, rest is name
name = &msg[1];
id = NO_RES;
for (i = 0; i < NUM_CLIENTS; ++i) {
if (clients[i][0] == '\0') {
strncpy(clients[i], name, NAME_LEN);
clients[i][NAME_LEN - 1] = '\0';
bzero(&coords[i], sizeof(coords[i]));
id = i + 1;
break;
}
}
if (sendto(sockfd,
&id, sizeof(id),
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error replying to client.");
exit(-1);
}
}
void do_unregister(int sockfd, struct sockaddr_in *clientaddr) {
unsigned char msg[UNREGISTER_CMD_LEN];
unsigned char id;
char res = NO_RES;
if (recv(sockfd, &msg, UNREGISTER_CMD_LEN, 0) == -1) {
perror("Error receiving unregister command.");
exit(-1);
}
id = msg[1] - 1;
if (id < NUM_CLIENTS) {
clients[id][0] = '\0';
res = SUCC_RES;
}
if (sendto(sockfd,
&res, sizeof(res),
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error responding to client.");
exit(-1);
}
}
int update_client(unsigned char id, gpscoords *pos) {
id -= 1;
if (id >= NUM_CLIENTS)
return -1;
memcpy(&coords[id], pos, sizeof(coords[id]));
return 0;
}
void do_update(int sockfd, struct sockaddr_in *clientaddr) {
/**
* Receive an update message over the socket and unpack the
* data. Then use the update_client function to update the server's
* internal representation of the client co-ordinates. Then respond to the
* client with the required value.
* Use recv to read the full message (of length UPDATE_CMD_LEN) into buffer.
* Unpack data, message of following format:
* U<id><fields of gpscoords>
* Character 'U' (meaning update), followed by ID of the client (unsigned char)
* and then the gpscoord structure in network format.
*
* 1. Unpack ID
* 2. Unpack coordinates with (int update_client(unsigned char id, gpscoords *pos)
* which takes ID and pointer to position struct, returns -1 on error and 0 on success
* Server should then respond to client using sendto function and reply
* NO_RES on error and SUCC_RES on success.
*/
char msg[UPDATE_CMD_LEN];
recv(sockfd, msg, UPDATE_CMD_LEN, flags);
fprintf(stderr, "do_update not implemented!\n");
exit(-1);
}
static gpscoords *get_client(char *name) {
for (int i = 0; i < NUM_CLIENTS; ++i) {
if (strcmp(name, clients[i]) == 0) {
return &coords[i];
break;
}
}
return NULL;
}
void do_get(int sockfd, struct sockaddr_in *clientaddr) {
char msg[GET_CMD_LEN];
char res[GET_RES_LEN];
char *name;
if (recv(sockfd, msg, GET_CMD_LEN, 0) == -1) {
perror("Error receiving get command.");
exit(-1);
}
name = &msg[1];
name[NAME_LEN - 1] = '\0';
gpscoords *pos = get_client(name);
if (pos == NULL) {
res[0] = NO_RES;
} else {
res[0] = SUCC_RES;
pack_gpscoords(pos, &res[1]);
}
if (sendto(sockfd,
&res, GET_RES_LEN,
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error sending result to client.");
exit(-1);
}
}
int serve(int sockfd) {
char cmd;
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
for (;;) {
if (recvfrom(sockfd,
&cmd, sizeof(cmd),
MSG_PEEK,
(struct sockaddr *)&clientaddr, &clientaddrlen) == -1) {
exit(-1);
}
switch (cmd) {
case CMD_REGISTER:
do_register(sockfd, &clientaddr);
break;
case CMD_UNREGISTER:
do_unregister(sockfd, &clientaddr);
break;
case CMD_UPDATE:
do_update(sockfd, &clientaddr);
break;
case CMD_GET:
do_get(sockfd, &clientaddr);
break;
default:
break;
}
}
}
void init_info() {
int i;
for (i = 0; i < NUM_CLIENTS; ++i) {
clients[i][0] = '\0';
}
}
int main(int argc, char **argv) {
int sockfd = create_dg_socket(SERVER_PORT);
if (sockfd == -1) {
fprintf(stderr, "Error creating socket!\n");
return -1;
}
init_info();
printf("Server ready.\n");
serve(sockfd);
// Note: server never terminates, we're relying on the system to clean up
// our open socket file descriptor (and shut it down)
return 0;
}
If you are looking for a way to safe and read data from char arrays that maybe will help you:
char buffer[5+sizeof(gpscoords)];
int *int_pointer;
gpscoords *gps_pointer;
int id=1;
gpscoords gps="some gps contend";
int id_frombuffer;
gpscoords gps_frombuffer;
char c_frombuffer;
buffer[0]='U';
int_pointer=(int*)&buffer;
int_pointer+=1;
*int_pointer=id;
gps_pointer=(gpscoords*)&buffer;
gps_pointer+=5;
*gpspointer=gps;
//send buffer
c_frombuffer=buffer[0];//c_frombuffer now contains 'U'
int_pointer=(int*)&buffer;
int_pointer+=1;
id_frombuffer=*int_pointer;//id_frombuffer now contains 1
gps_pointer=(gpscoords*)&buffer;
gpscoords+=5;
gps_frombuffer=*pointer;//gps_frombuffer now contains "some gps contend"
As an example if your client code looks like that:
void sendupdate(unsigned char id,gpscoords gps)
{
char buffer[2+sizeof(gpscoords)];
gpscoords *gps_pointer;
buffer[0]='U';
buffer[1]=id;
gps_pointer=(gpscoords*)&buffer;
gps_pointer+=2;
*gpspointer=gps;
send(socket, buffer, 2+sizeof(gpscoords), flags);
}
your server function should look like that:
void do_update(int sockfd, struct sockaddr_in *clientaddr)
{
char buffer[2+sizeof(gpscoords)];
recv(sockfd, buffer, 2+sizeof(gpscoords), flags);
unsigned char id_frombuffer=buffer[1];
gpscoords *gpspointer=(gpscoords*)&buffer;
gpspointer+=2;
update_client(id_frombuffer, gpspointer);
}

C client/server issue

I have this C server:
#define TRUE 1
#define FALSE 0
#define BUFSIZE 256
#define SERVER_PORT 8887
int main ( int argc, char *argv[])
{
signal(SIGCHLD, SIG_IGN);
printf("START");
int ls; // listen socket
int s; // socket descriptor
int n; // byte send / receive
int waitSize; // queue's length
struct sockaddr_in serverAddr;
struct sockaddr_in clientAddr;
int clientAddrLen = sizeof( clientAddr );
memset(&serverAddr,0,sizeof(serverAddr));
serverAddr.sin_family=AF_INET;
serverAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
serverAddr.sin_port=htons(SERVER_PORT);
if( (ls = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("Error: socket creation");
exit(1);
}
int so_reuseaddr = TRUE;
if(setsockopt(ls,SOL_SOCKET,SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr))<0)
{
perror("Error: general");
exit(1);
}
if(bind(ls, (struct sockaddr *) &serverAddr, sizeof(serverAddr))<0)
{
perror("Error: bind error");
exit(1);
}
if(listen(ls,waitSize)<0)
{
perror("Error: listen operation");
exit(1);
}
while(1)
{
if ((s=accept(ls,(struct sockaddr*) &clientAddr, &clientAddrLen))<0)
{
perror("Error: accepting error");
exit(1);
}
if( fork() == 0)
{
while(1)
{
char cmd[BUFSIZE];
char var1[BUFSIZE];
char var2[BUFSIZE];
char string[100];
memset(cmd, 0, sizeof(cmd));
memset(var1, 0, sizeof(var1));
memset(var2, 0, sizeof(var2));
memset(string, 0, sizeof(string));
if( readLine(s, cmd, sizeof(cmd)) == 0)
{
exit(0);
}
if( readLine(s, var1, sizeof(var1)) == 0)
{
exit(0);
}
if( readLine(s, var2, sizeof(var2)) == 0)
{
exit(0);
}
removeNewLine(cmd);
removeNewLine(var1);
removeNewLine(var2);
if( strcmp(cmd, "somma") == 0)
sprintf(string, "%d\n", atoi(var1) + atoi(var2));
else if ( strcmp( cmd, "diversi") == 0 )
if( strcmp( var1, var2) != 0)
sprintf(string,"The strings %s e %s are not equals\n", var1, var2);
else sprintf(string,"test fals\n");
printf("%s", string);
writeLine(s, string, strlen(string));
}
}
else
{
close(s);
}
}
close(s);
exit(0);
}
functions used in the server code:
int readLine( int fd, char* str, int bufferSize)
{
return readToDel(fd, '\n', str, bufferSize);
}
int readToDel( int fd, char delimiter, char* str, int bufferSize)
{
int n;
int byteLetti =0;
int index=0;
do /* Read characters until NULL or end-of-input */
{
if( (n = read (fd, str+index, 1)) < 0)
{
perror("Errore: lettura dal file descriptor fallita");
exit(1);
}
byteLetti+=n;
}
while (n > 0 && *(str+index++) != delimiter && index < bufferSize);
return byteLetti; /* Return false if end-of-input */
}
void removeNewLine( char *s )
{
removeDel(s, "\r\n");
}
void removeDel( char *s, char *del)
{
s[strcspn ( s, del )] = '\0';
}
My problem is that when I execute this program by terminal( I get a couple of warnings but I think is not important for this reason) the program is like doesn't start ( I don't see the first printf in the program (START string)).
In the terminal is only white character that blinks
I don't understand why.
I tested it on Mac and Linux
Your stdout is being buffered because there is no \n at the end of your printed string.

Chatting server using epoll - unexpected behavior

I'm working on writing a simple chatting server-client C program using epoll. I'm writing and testing it in Xubuntu, and I found something strange. Message from server to client is delivered well. But Message from client to server is delivered at the moment when I push enter key at 'SERVER SIDE(putty window)'
For example, if I type 'Hello World' in the client window and push enter key, the message doesn't show on the server side, however, when I push enter key on the server side, 'Hello World' shows on the window!
I think something is wrong in server.c but I can't find what's wrong. I used epoll and let it monitor EPOLLIN|EPOLLOUT to receive and send messages.
In other hand, I wrote client program with multi-threading.
Full src are below without header.
Any comment will be appreciated. Thank you!
server.c
int main(int argc, char *argv[])
{
int serv_sock, clnt_sock;
struct sockaddr_in serv_adr, clnt_adr;
socklen_t adr_sz;
int str_len, i;
char buf[BUF_SIZE];
struct epoll_event *ep_events;
struct epoll_event event;
int epfd, event_cnt;
if(argc!=2) {
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
serv_sock=socket(PF_INET, SOCK_STREAM, 0);
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_adr.sin_port=htons(atoi(argv[1]));
if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr))==-1)
error_handling("bind() error");
if(listen(serv_sock, 5)==-1)
error_handling("listen() error");
epfd=epoll_create(EPOLL_SIZE);
ep_events=malloc(sizeof(struct epoll_event)*EPOLL_SIZE);
//set_nonblocking_mode(serv_sock);
event.events=EPOLLIN;
event.data.fd=serv_sock;
epoll_ctl(epfd, EPOLL_CTL_ADD, serv_sock, &event);
while(1) {
event_cnt=epoll_wait(epfd, ep_events, EPOLL_SIZE, -1);
if(event_cnt==-1) {
puts("epoll_wait() error");
break;
}
for(i=0; i<event_cnt; i++) {
if(ep_events[i].data.fd==serv_sock) {
adr_sz=sizeof(clnt_adr);
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &adr_sz);
//set_nonblocking_mode(clnt_sock);
event.events=EPOLLIN|EPOLLOUT;
event.data.fd=clnt_sock;
epoll_ctl(epfd, EPOLL_CTL_ADD, clnt_sock, &event);
printf("connected client: %d \n", clnt_sock);
}
else {
if((ep_events[i].events & EPOLLIN) == EPOLLIN) {
memset(buf, 0, BUF_SIZE);
str_len=read(ep_events[i].data.fd, buf, BUF_SIZE-1);
buf[str_len] = 0;
if(str_len==0) { // close request!
epoll_ctl(epfd, EPOLL_CTL_DEL, ep_events[i].data.fd, NULL);
close(ep_events[i].data.fd);
printf("closed client: %d \n", ep_events[i].data.fd);
}
/*
else if(str_len < 0) {
if(errno == EAGAIN)
break;
}*/
else {
fputs(buf, stdout);
}
}
if((ep_events[i].events & EPOLLOUT) == EPOLLOUT) {
fgets(buf, BUF_SIZE, stdin);
if(!strcmp(buf, "q\n") || !strcmp(buf, "Q\n")) {
epoll_ctl(epfd, EPOLL_CTL_DEL, ep_events[i].data.fd, NULL);
close(ep_events[i].data.fd);
printf("closed client: %d \n", ep_events[i].data.fd);
}
else {
write(ep_events[i].data.fd, buf, strlen(buf));
}
}
}
}
}
close(serv_sock);
close(epfd);
return 0;
}
void set_nonblocking_mode(int fd)
{
int flag = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flag|O_NONBLOCK);
}
void error_handling(char *buf)
{
fputs(buf, stderr);
fputc('\n', stderr);
exit(1);
}
client.c
void * send_msg(void * arg);
void * recv_msg(void * arg);
void error_handling(char * msg);
char name[NAME_SIZE]="[DEFAULT]";
char msg[BUF_SIZE];
int main(int argc, char *argv[])
{
int sock;
struct sockaddr_in serv_addr;
pthread_t snd_thread, rcv_thread;
void * thread_return;
if(argc!=4) {
printf("Usage : %s <IP> <port> <name>\n", argv[0]);
exit(1);
}
sprintf(name, "[%s]", argv[3]);
sock=socket(PF_INET, SOCK_STREAM, 0);
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
serv_addr.sin_port=htons(atoi(argv[2]));
if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)
error_handling("connect() error");
pthread_create(&snd_thread, NULL, send_msg, (void*)&sock);
pthread_create(&rcv_thread, NULL, recv_msg, (void*)&sock);
pthread_join(snd_thread, &thread_return);
pthread_join(rcv_thread, &thread_return);
close(sock);
return 0;
}
void * send_msg(void * arg) // send thread main
{
int sock=*((int*)arg);
char name_msg[NAME_SIZE+BUF_SIZE];
while(1)
{
fgets(msg, BUF_SIZE, stdin);
if(!strcmp(msg,"q\n")||!strcmp(msg,"Q\n"))
{
close(sock);
exit(0);
}
sprintf(name_msg,"%s %s", name, msg);
write(sock, name_msg, strlen(name_msg));
}
return NULL;
}
void * recv_msg(void * arg) // read thread main
{
int sock=*((int*)arg);
char name_msg[NAME_SIZE+BUF_SIZE];
int str_len;
while(1)
{
str_len=read(sock, name_msg, NAME_SIZE+BUF_SIZE-1);
if(str_len==-1)
return (void*)-1;
name_msg[str_len]=0;
fputs(name_msg, stdout);
}
return NULL;
}
void error_handling(char *msg)
{
fputs(msg, stderr);
fputc('\n', stderr);
exit(1);
}

Resources