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.
Related
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);
}
I've implemented a network chat client in C that looks like this:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "stdbool.h"
#include "sys/socket.h"
#include "sys/types.h"
#include "netdb.h"
#include "netinet/in.h"
#include "pthread.h"
#include "errno.h"
#define MESSAGE_BUFFER 500
#define USERNAME_BUFFER 10
typedef struct {
char* prompt;
int socket;
} thread_data;
// Connect to server
void * connect_to_server(int socket_fd, struct sockaddr_in *address) {
int response = connect(socket_fd, (struct sockaddr *) address, sizeof *address);
if (response < 0) {
fprintf(stderr, "socket() failed: %s\n", strerror(errno));
printf("Failed to connect\n");
exit(1);
} else {
printf("Connected\n");
}
}
// Get message from stdin and send to server
void * send_message(char prompt[USERNAME_BUFFER+4], int socket_fd, struct sockaddr_in *address) {
printf("%s", prompt);
char message[MESSAGE_BUFFER];
char final_message[MESSAGE_BUFFER+USERNAME_BUFFER+1];
while (fgets(message, MESSAGE_BUFFER, stdin) != NULL) {
memset(final_message,0,strlen(final_message)); // Clear final message buffer
strcat(final_message, prompt);
strcat(final_message, message);
printf("\n%s", prompt);
if (strncmp(message, "/quit", 5) == 0) {
printf("Closing connection...\n");
exit(0);
}
sendto(socket_fd, final_message, MESSAGE_BUFFER+USERNAME_BUFFER+1, 0, (struct sockaddr *) &address, sizeof address);
}
}
void * receive(void * threadData) {
int socket_fd, response;
char message[MESSAGE_BUFFER];
thread_data* pData = (thread_data*)threadData;
socket_fd = pData->socket;
char* prompt = pData->prompt;
memset(message, 0, MESSAGE_BUFFER); // Clear message buffer
// Print received message
while(true) {
response = recvfrom(socket_fd, message, MESSAGE_BUFFER, 0, NULL, NULL);
if (response) {
printf("\nServer> %s", message);
printf("%s", prompt);
fflush(stdout); // Make sure "User>" gets printed
}
}
}
int main(int argc, char**argv) {
long port = strtol(argv[2], NULL, 10);
struct sockaddr_in address, cl_addr;
char * server_address;
int socket_fd, response;
char prompt[USERNAME_BUFFER+4];
char username[USERNAME_BUFFER];
pthread_t thread;
// Check for required arguments
if (argc < 3) {
printf("Usage: client ip_address port_number\n");
exit(1);
}
// Get user handle
printf("Enter your user name: ");
fgets(username, USERNAME_BUFFER, stdin);
username[strlen(username) - 1] = 0; // Remove newline char from end of string
strcpy(prompt, username);
strcat(prompt, "> ");
server_address = argv[1];
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(server_address);
address.sin_port = port;
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
connect_to_server(socket_fd, &address);
// Create data struct for new thread
thread_data data;
data.prompt = prompt;
data.socket = socket_fd;
// Create new thread to receive messages
pthread_create(&thread, NULL, receive, (void *) &data);
// Send message
send_message(prompt, socket_fd, &address);
// Close socket and kill thread
close(socket_fd);
pthread_exit(NULL);
return 0;
}
This works perfectly fine with a server that I wrote for it. However, when I try to make it play nicely with a server in another language, or one that someone else wrote, things fall apart, and I can't establish a connection. Shouldn't these work independently from each other? If both work separately, they should work together, from what I gather.
For example, if I try to use my client with the server in the answer to this question, things no longer work. I've tested both of them, and they work fine separately, just not together. I've looked at the output of stderr when connecting, but all I get is a Connection refused error with no more information.
Is there something obvious I'm missing trying to get these to work together? If someone could demonstrate how my client could work with the example server, that would be super helpful.
address.sin_port = port;
The problem is here. It should be
address.sin_port = htons(port);
in both client and server.
There are other problems.
fprintf(stderr, "socket() failed: %s\n", strerror(errno));
This should be
fprintf(stderr, "connect() failed: %s\n", strerror(errno));
Then:
sendto(socket_fd, final_message, MESSAGE_BUFFER+USERNAME_BUFFER+1, 0, (struct sockaddr *) &address, sizeof address);
This should be:
send(socket_fd, final_message, strlen(final_message)+1, 0);
You don't need sendto(), as you are already connected, and you don't need to send anything beyond the trailing null. As a matter of fact you can reduce the entire method to this:
void * send_message(char prompt[USERNAME_BUFFER+4], int socket_fd, struct sockaddr_in *address) {
printf("%s", prompt);
char message[MESSAGE_BUFFER];
while (fgets(message, MESSAGE_BUFFER, stdin) != NULL) {
if (strncmp(message, "/quit", 5) == 0) {
printf("Closing connection...\n");
close(socket_fd);
exit(0);
}
send(socket_fd, prompt, strlen(prompt), 0);
send(socket_fd, message, strlen(message)+1, 0);
printf("\n%s", prompt);
}
}
Then:
if (response) {
printf("\nServer> %s", message);
printf("%s", prompt);
fflush(stdout); // Make sure "User>" gets printed
}
That should be:
if (response == -1) {
fprintf(stderr, "recv() failed: %s\n", strerror(errno));
break;
} else if (response == 0) {
printf("\nPeer disconnected\n");
break;
} else {
printf("\nServer> %s", message);
printf("%s", prompt);
fflush(stdout); // Make sure "User>" gets printed
}
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);
}
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.
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);
}