Related
I would like to add the functionality of evaluating arithmetic expressions for my simple client server application but do not know how. A client should be asked to input an arithmetic expression and the server should return an evaluation of that expression. The expression should separated into operation(+,-,/,*) and two non negative integer arguments. Server: This must implement an “Arithmetic Service” consisting of a dispatcher and the four operations
add, subtract, multiply and divide which should have identical prototypes:
Status op( int , int , int *); // the last argument is for the result
CLIENT CODE
#include "connection.h"
int clientSocket, z;
SocketAddress serverAddr, clientAddr, rSA;
socklen_t addr_size;
char _message[SIZE], reply[SIZE];
void main(int argc, char **argv)
{
int aPort = IPPORT_RESERVED + getuid();
int rPort = IPPORT_RESERVED + getuid() + 1;
if (argc <= 1)
{
printf("\nUsage: client server_name ??\n example client 127.0.0.1\n");
printf("Use q to close the session.\n");
exit(BAD);
}
z = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
makeReceiverSA(&rSA, rPort);
clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (clientSocket < 0)
{
perror("Socket creation failed!");
exit(BAD);
}
else
{
makeLocalSA(&clientAddr);
}
bind(z, (struct sockaddr *)&rSA, sizeof(SocketAddress));
if (bind(clientSocket, (struct sockaddr *)&clientAddr, sizeof(SocketAddress)) != 0)
{
perror("Socket binding failed!");
close(clientSocket);
exit(BAD);
}
printSA(clientAddr);
makeDestSA(&serverAddr, argv[1], aPort);
makeReceiverSA(&rSA, rPort);
printSA(serverAddr);
while (strlen(_message) != 1 && _message[0] != 'q')
{
printf("\nEnter message to send: ");
fgets(_message, SIZE, stdin);
Message m, r;
memcpy(m.data, _message, strlen(_message));
m.length = strlen(_message);
r.length = SIZE;
if (DoOperation(&m, &r, clientSocket, serverAddr) == OK)
{
memcpy(r.data, reply, strlen(reply));
printf("\nResponse: %s\n", r.data);
}
}
}
Status DoOperation(Message *message, Message *reply, int s, SocketAddress serverSA)
{
Status ret;
if (message->length > SIZE)
{
printf("\nError: \n\tCode: %d\n\tMessage: BAD Message Length\n", WRONGLENGTH);
return WRONGLENGTH;
}
ret = UDPsend(s, message, serverSA);
if (ret == BAD)
return BAD;
ret = UDPreceive(z, reply, &rSA);
if (ret == BAD)
return BAD;
return OK;
}
Status UDPsend(int s, Message *m, SocketAddress dest)
{
ssize_t n;
n = sendto(s, m->data, m->length, 0, (struct sockaddr *)&dest, sizeof(SocketAddress));
if (n < 0)
{
printf("\nError: \n\tCode: %d\n\tMessage: Unrecoverable error\n", BAD);
return BAD;
}
if (n != m->length)
return OK;
}
Status UDPreceive(int s, Message *m, SocketAddress *origin)
{
ssize_t n;
socklen_t a = sizeof(SocketAddress);
n = recvfrom(s, reply, SIZE, 0, (struct sockaddr *)&origin, &a);
if (n < 0)
{
printf("\nError: \n\tCode: %d\n\tMessage: Unrecoverable error\n", BAD);
return BAD;
}
if (strlen(reply) > SIZE)
{
printf("\nError: \n\tCode: %d\n\tMessage: BAD Message Length\n", WRONGLENGTH);
return WRONGLENGTH;
}
return OK;
}
HEADER FILE
#include <stdio.h> /* standard C i/o facilities */
#include <unistd.h> /* Unix System Calls */
#include <sys/types.h> /* system data type definitions */
// #include <sys/wait.h> /* System Socket wait definitions */
#include <sys/socket.h> /* socket specific definitions */
#include <netinet/in.h> /* INET constants and stuff */
#include <arpa/inet.h> /* IP address conversion stuff */
#include <string.h>
#include <stdlib.h> /* needed for atoi() */
#include <netdb.h>
struct hostent *gethostbyname() ;
#ifndef SIZE
#define SIZE 1000
#endif
typedef enum {
OK, // operation successful
BAD, // unrecoverable error
WRONGLENGTH // BAD message length supplied
} Status;
typedef struct sockaddr_in SocketAddress;
typedef struct
{
unsigned int length;
unsigned char data[SIZE];
} Message;
extern void printSA(SocketAddress sa) ;
extern void makeDestSA(SocketAddress * sa, char *hostname, int port) ;
extern void makeLocalSA(SocketAddress *sa) ;
extern void receiver(int port) ;
extern void sender(char *message1, char *machine, int port);
extern Status DoOperation(Message *message, Message *reply, int s, SocketAddress serverSA);
extern Status GetRequest(Message *callMessage, int s, SocketAddress *clientSA);
extern Status SendReply(Message *replyMessage, int s, SocketAddress clientSA);
/*
* To return BAD if sendto/recvfrom return negatives
*/
extern Status UDPsend(int s, Message *m, SocketAddress dest);
extern Status UDPreceive(int s, Message *m, SocketAddress *origin);
/*print a socket address */
void printSA(SocketAddress sa)
{
printf("sa = %d, %s, %d\n",
sa.sin_family, inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
}
/* make a socket address for a destination whose machine and port
are given as arguments */
void makeDestSA(SocketAddress * sa, char *hostname, int port)
{
struct hostent *host;
sa->sin_family = AF_INET;
if((host = gethostbyname(hostname))== NULL) {
printf("Unknown host name\n");
exit(-1);
}
sa->sin_addr = *(struct in_addr *) (host->h_addr);
sa->sin_port = htons(port);
}
/* make a socket address using any of the addressses of this computer
for a local socket on any port */
void makeLocalSA(SocketAddress *sa)
{
sa->sin_family = AF_INET;
sa->sin_port = htons(0);
sa->sin_addr.s_addr = htonl(INADDR_ANY);
}
/* make a socket address using any of the addressses of this computer
for a local socket on given port */
void makeReceiverSA(SocketAddress *sa, int port)
{
sa->sin_family = AF_INET;
sa->sin_port = htons(port);
sa->sin_addr.s_addr = htonl(INADDR_ANY);
}
/*receive two messages via s new socket,
print out the messages received and close the socket
bind to any of the addresses of this computer
using port given as argument */
void receiver(int port)
{
char message1[SIZE], message2[SIZE];
SocketAddress mySocketAddress, aSocketAddress;
int s, n;
socklen_t aLength;
int i;
if((s = socket(AF_INET, SOCK_DGRAM, 0))<0) {
perror("socket failed");
return;
}
makeReceiverSA(&mySocketAddress, port);
if( bind(s, (struct sockaddr *)&mySocketAddress, sizeof(SocketAddress))!= 0){
perror("Bind failed\n");
close(s);
return;
}
printSA(mySocketAddress);
aLength = sizeof(aSocketAddress);
aSocketAddress.sin_family = AF_INET;
if((n = recvfrom(s, message1, SIZE, 0, (struct sockaddr *)&aSocketAddress, &aLength))<0)
perror("Receive 1") ;
else{
printSA(aSocketAddress);
for(i=0; i<n; i++) printf("M:%d", message1[i]);
printf(" Received Message:(%s)length = %d \n",
message1,n);
}
if((n = recvfrom(s, message2, SIZE, 0, (struct sockaddr *)&aSocketAddress, &aLength))<0)
perror("Receive 2");
else {
printf("Received Message:(%s)length = %d \n",
message2,n);
}
close(s);
}
/*do send after receive ready, open socket
bind socket to local internet port
use any of the local computer's addresses
send two messages with given lengths to machine and port
close socket
*/
void sender(char *message1,char *machine, int port)
{
int s, n;
char message[SIZE];
SocketAddress mySocketAddress, yourSocketAddress;
if(( s = socket(AF_INET, SOCK_DGRAM, 0))<0) {
perror("socket failed");
return;
}
/*
if((x = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &arg, sizeof(arg))<0)
perror("setsockopt SO_BROADCAST---");
exit(-1);
*/
makeLocalSA(&mySocketAddress);
if( bind(s, (struct sockaddr *)&mySocketAddress, sizeof(SocketAddress))!= 0){
perror("Bind failed\n");
close (s);
return;
}
printSA(mySocketAddress);
makeDestSA(&yourSocketAddress,machine, port);
printSA(yourSocketAddress);
strcpy(message,message1);
if( (n = sendto(s, message, strlen(message), 0, (struct sockaddr *)&yourSocketAddress,
sizeof(SocketAddress))) < 0)
perror("Send failed\n");
if(n != strlen(message)) printf("sent %d\n",n);
close(s);
}
#include <sys/time.h>
/* use select to test whether there is any input on descriptor s*/
int anyThingThere(int s)
{
unsigned long read_mask;
struct timeval timeout;
int n;
timeout.tv_sec = 1; /*seconds wait*/
timeout.tv_usec = 0; /* micro seconds*/
read_mask = (1<<s);
if((n = select(32, (fd_set *)&read_mask, 0, 0, &timeout))<0)
perror("Select fail:\n");
// else printf("n = %d\n", n);
return n;
}
SERVER CODE
#include "connection.h"
int serverSocket;
SocketAddress serverAddr, clientAddr;
socklen_t addr_size, n;
int i;
char _message[SIZE];
int main(int argc, char **argv)
{
int aPort = IPPORT_RESERVED + getuid();
serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (serverSocket < 0)
{
perror("Socket creation failed!\n");
exit(BAD);
}
else
{
makeReceiverSA(&serverAddr, aPort);
}
if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(SocketAddress)) != 0)
{
perror("Socket binding failed!\n");
close(serverSocket);
exit(BAD);
}
printSA(serverAddr);
addr_size = sizeof(clientAddr);
makeDestSA(&clientAddr, "127.0.0.1", aPort+1);
// clientAddr.sin_family = AF_INET;
while (strlen(_message) != 1 && _message[0] != 'q')
{
Message m, r;
char* art = "Message received!";
memcpy(r.data, art, strlen(art));
r.length = strlen(art);
if (anyThingThere(serverSocket) > 0)
if (GetRequest(&m, serverSocket, &clientAddr) == OK)
{
memcpy(_message, m.data, m.length);
printf("\nReceived Message: %s\n", m.data);
Status ret = SendReply(&r, serverSocket, clientAddr);
}
}
}
Status SendReply(Message *replyMessage, int s, SocketAddress clientSA)
{
printSA(clientSA);
Status ret;
ret = UDPsend(s, replyMessage, clientSA);
return OK;
}
Status GetRequest(Message *callMessage, int s, SocketAddress *clientSA)
{
Status ret = UDPreceive(s, callMessage, clientSA);
if (ret == BAD)
return BAD;
if (strlen(_message) > SIZE)
{
printf("\nError: \n\tCode: %d\n\tMessage: BAD Message Length\n", WRONGLENGTH);
return WRONGLENGTH;
}
else
return OK;
}
Status UDPsend(int s, Message *m, SocketAddress dest)
{
ssize_t n;
n = sendto(s, m->data, m->length, 0, (struct sockaddr *)&dest, sizeof(SocketAddress));
if (n < 0)
{
perror("Send Error:");
printf("\nError: \n\tCode: %d\n\tMessage: Unrecoverable error\n", BAD);
return BAD;
}
if (n != m->length)
return OK;
}
Status UDPreceive(int s, Message *m, SocketAddress *origin)
{
ssize_t n;
socklen_t a = sizeof(SocketAddress);
n = recvfrom(s, _message, SIZE, 0, (struct sockaddr *)&origin, &a);
// printf("%ld\n", n);
// printf("%s\n", _message);
// memcpy(&m->data, _message, strlen(_message));
// printf("%s\n", m->data);
// m->length = strlen(_message);
if (n < 0)
{
printf("\nError: \n\tCode: %d\n\tMessage: Unrecoverable error\n", BAD);
return BAD;
}
if (strlen(_message) > SIZE)
{
printf("\nError: \n\tCode: %d\n\tMessage: BAD Message Length\n", WRONGLENGTH);
return WRONGLENGTH;
}
return OK;
}
I have a problem with multiple clients sending a notification, every interval of time, with some kind of information to a server. The problem occurs when more than one client sends the notification at the same moment, only one will be sent.
Specifically, they both print "Sending nofication", but after that only one prints "Sent ...", the server receives only one aswell.
This is my client thread function
void* Notification_Handler (void* args) {
int nc = *((int*)args); // id of the client
struct sockaddr_un addr;
memset(&addr, '0', sizeof(addr));
addr.sun_family= AF_UNIX;
strncpy(addr.sun_path, SOCKNAME_MANAGER, strlen(SOCKNAME_MANAGER)+1);
int fd_socket;
SYSCALL(fd_socket, socket(AF_UNIX, SOCK_STREAM, 0), "socket");
int notused;
SYSCALL(notused, connect(fd_socket, (struct sockaddr*)&addr, sizeof(addr)), "connect");
int res;
struct timespec *ts_notification = (struct timespec *)malloc(sizeof(struct timespec));
ts_notification->tv_sec = (4000)/1000;
ts_notification->tv_nsec = ((4000)%1000)*1000000;
while (c_status[nc-1]==1) { // while this client is open (1: open, 0:closed)
do {
res = nanosleep(ts_notification, ts_notification); // notification every interval
} while (res && errno==EINTR);
if (c_status[nc-1]==0) break;
sendToManager(nc, fd_socket);
}
free(ts_notification);
close(fd_socket);
pthread_exit((void*)EXIT_SUCCESS);
}
and this is the SendToManager function for sending the data
void sendToManager (int nc, int fd_socket) {
printf("Handler[%d]: sending notification\n", nc);
char message[64];
snprintf(message, sizeof(message), "Cashier:%d", nc);
int len= strlen(message);
int n;
if ((n=write_h(fd_socket, &len, sizeof(int)))==-1) {
fprintf(stderr, "write len failed\n");
pthread_exit((void*)EXIT_FAILURE);
}
if ((n=write_h(fd_socket, message, len))==-1) {
fprintf(stderr, "write info failed\n");
pthread_exit((void*)EXIT_FAILURE);
}
printf("Sent: %s\n", message);
}
SYSCALL and write_h are just some macro/function from an header file
#define SYSCALL(r, sc, str) \
if ((r=sc) == -1) { \
perror(str); \
exit(errno); \
}
static inline int write_h (long fd, void* buffer, size_t size) {
int res;
size_t left = size;
char *bufptr = (char*)buffer;
while(left>0) {
if ((res=write((int)fd ,bufptr,left))==-1) {
if (errno == EINTR) continue;
return -1;
}
if (res==0) return 0;
left -= res;
bufptr += res;
}
return 1;
}
The server spawns a thread for every connect request he receives. Is my function not thread-safe or some info/variables are shared?
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
}
When I try to send some basic UDP message it looks like it doesn't send it.
I tried to run couple of examples that I found online.
I am using SocketTest v3.0.0 for testing server/client.
When I tested TCP sending everything worked as expected, but I UDP case it simply doesn't.
Can you provide some really basic UDP send code snippet ?
For example the receiver will be on localhost and the message will contain "test" and it will be fixed length ?
And I have one more small question. It I send the message on local host can the application(server) itself receive it and think that someone else has send it (causing looping) because it does not connect to some peer it just send the message and listen on same ip-port ?
Thanks :)
You have a lot of usefull examples here: https://nikhilm.github.io/uvbook/networking.html
uv_loop_t *loop;
uv_udp_t send_socket;
uv_udp_t recv_socket;
int main() {
loop = uv_default_loop();
uv_udp_init(loop, &recv_socket);
struct sockaddr_in recv_addr;
uv_ip4_addr("0.0.0.0", 68, &recv_addr);
uv_udp_bind(&recv_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
uv_udp_recv_start(&recv_socket, alloc_buffer, on_read);
uv_udp_init(loop, &send_socket);
struct sockaddr_in broadcast_addr;
uv_ip4_addr("0.0.0.0", 0, &broadcast_addr);
uv_udp_bind(&send_socket, (const struct sockaddr *)&broadcast_addr, 0);
uv_udp_set_broadcast(&send_socket, 1);
uv_udp_send_t send_req;
uv_buf_t discover_msg = make_discover_msg();
struct sockaddr_in send_addr;
uv_ip4_addr("255.255.255.255", 67, &send_addr);
uv_udp_send(&send_req, &send_socket, &discover_msg, 1, (const struct sockaddr *)&send_addr, on_send);
return uv_run(loop, UV_RUN_DEFAULT);
}
Here is a basic example that shows sending UDP packets and receiving the response from the other side:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
uv_udp_t udp_socket;
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
buf->base = malloc(suggested_size);
buf->len = suggested_size;
}
void on_read(uv_udp_t *socket, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags){
if (nread < 0) {
fprintf(stderr, "read error %s\n", uv_err_name(nread));
uv_close((uv_handle_t*) socket, NULL);
} else if (nread > 0) {
char sender[17] = { 0 };
uv_ip4_name((const struct sockaddr_in*) addr, sender, 16);
printf("recv from %s:%.*s\n", sender, (int)buf->len, buf->base);
}
if (buf && buf->base) {
/* releases the buffer allocated on alloc_buffer() */
free(buf->base);
}
}
void on_send(uv_udp_send_t *req, int status) {
if (status) {
fprintf(stderr, "send error %s\n", uv_strerror(status));
}
/* releases the request allocated on send_msg() */
if (req) free(req);
}
void send_msg(char *msg){
uv_buf_t buf = uv_buf_init(msg, strlen(msg)+1);
struct sockaddr_in send_addr;
uv_ip4_addr("123.45.67.89", 2222, &send_addr);
uv_udp_send_t *send_req = malloc(sizeof(uv_udp_send_t));
uv_udp_send(send_req, &udp_socket, &buf, 1, (const struct sockaddr *)&send_addr, on_send);
}
int main() {
uv_loop_t *loop = uv_default_loop();
uv_udp_init(loop, &udp_socket);
struct sockaddr_in recv_addr;
uv_ip4_addr("0.0.0.0", 2345, &recv_addr);
uv_udp_bind(&udp_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
uv_udp_recv_start(&udp_socket, alloc_buffer, on_read);
send_msg("hi there!");
send_msg("hello world");
return uv_run(loop, UV_RUN_DEFAULT);
}
You may try stream route handler, although is new, but it's reliable and had tested with heavy traffic data transaction.
Example
void read_data(srh_request_t *req);
void read_data(srh_request_t *req) {
char *a = "CAUSE ERROR FREE INVALID";
if (strncmp( (char*)req->in_buff->start, "ERROR", 5) == 0) {
free(a);
}
// printf("%d, %.*s\n", i++, (int) (req->in_buff->end - req->in_buff->start), req->in_buff->start);
srh_write_output_buffer_l(req, req->in_buff->start, (req->in_buff->end - req->in_buff->start));
// printf("%d, %.*s\n", i++, (int) (req->out_buff->end - req->out_buff->start), req->out_buff->start);
}
int main(void) {
srh_instance_t * instance = srh_create_routing_instance(24, NULL, NULL);
srh_add_udp_fd(instance, 12345, read_data, 1024, NULL);
srh_add_tcp_fd(instance, 3232, read_data, 64, NULL);
srh_start(instance, 1);
return 0;
}
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.