C submit command to server from client - c

I have a client-server application which runs on UDP ( I need it UDP not tcp ).
A client can send a message to server and it's working fine and vice versa.
I want the client to be able to pass a message as "_connect game1 10" and trigger a function on the server correspondingly which is called _connect(char *name, int num).
How can this be performed to analyse each command to trigger what command ? and is serialisation is a solution and how to implement it.

You can do something on the lines of the following steps
1. Create a message structure
typedef struct info
{
char clientReq[MAX_LENGTH];
char sub[MAX_LENGTH];
u_int32_t value;
u_int16_t end; //Set for the packet which closes the connection
}messageInfo;
On Client
Create socket and bind locally //and connect to server socket(optionally)
fd = socket( family, SOCK_DGRAM, 0 );
//handle error
struct sockaddr_in peerV4;
struct sockaddr_in clientV4;
rc = bind(fd,(struct sockaddr *) &clientV4,
sizeof clientV4);
//error handling
Send the packet data to server.
//update peer(server) socket info here
peerV4.sin_family = AF_INET;
peerV4.sin_port = htons(serverPort);
peerV4.sin_addr.s_addr = "x.x.x.x";
uint8_t *tBuf = (uint8_t *)malloc(sizeof (info)); //memset to zero
info *pHeader = (info *)tBuf;
pHeader->value = htonl(10); //local value to send
pHeader->end = htons(0);
pHeader->clientReq = "connect";
pheader->sub = "game1";
sendto(serverSock, tBuf, sizeof(info),0
,(struct sockaddr *) &peerV4,
sizeof(peerV4));
Send last packet and close local socket.
pHeader->end = htons(1); // so the server closes the socket
//send packet
close(fd);
On Server
1. Create a UDP socket, bind to a local address wait for client to send you the data and use recvfrom
fd = socket( family, SOCK_DGRAM, 0 );
//bind socket
uint8_t *recvBuf = (uint8_t *)malloc(sizeof(info));
info *pheader = (info *)recvBuf;
int currLen = recvfrom( fd, recvBuf,
mBufLen),0,(struct sockaddr *)&peerV4,
&sockaddrLen);
//error handling
if(currLen > 0)
{
if(htons(pheader->end) == 1)
//close socket
char *localSub = pheader->sub;
char *localRecv = pheader->clientReq;
//do something with the values on the server like
if (strcasecmp(localRecv,"connect") == 0) //pseudo
connect(sub,pheader->value)
}

Related

Reading UDP packets with several clients

I have an application installed locally (not developed by me), which broadcasts UDP packets every second.
Reading the packets from my application (developed in C++ in Windows) which also is locally installed, works fine.
WSADATA data;
WORD version = MAKEWORD(2, 2);
int wsOK = WSAStartup(version, &data);
SOCKET serverIn = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
sockaddr_in serverHint;
serverHint.sin_addr.S_un.S_addr = INADDR_ANY;
serverHint.sin_family = AF_INET;
serverHint.sin_port = htons(UDP_RECEIVE_PORT);
bind(serverIn, (sockaddr*)&serverHint, sizeof(serverHint));
sockaddr_in client;
int clientSize = sizeof(client);
int RECIEVE_BUFFER_SIZE = 65507;
char* recieveBuffer = new char[RECIEVE_BUFFER_SIZE];
while(updating)
{
int bytesIn = recvfrom(serverIn, recieveBuffer, RECIEVE_BUFFER_SIZE, 0, (sockaddr*)&client, &clientSize);
}
closesocket(serverIn);
WSACleanup();
But I recently noticed while I was testing some code, while my app was running, that the bind(...)
function returned an error code of 10048 (WSAEADDRINUSE). Hence, it seems the first client bound to listen for the UDP packets is the only one who can listen, and the other clients is unable to read the broadcasted UDP packets.
So then I added the SO_REUSEADDR option before calling the bind(...) function to be able to bind successfully to the socket:
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
setsockopt((SOCKET)serverIn, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptVal, bOptLen);
That works, but the recvfrom(...) function then does not recieve any data at all! I guess it waits for the other client to close its socket.
Next solution is to initialize the socket with SOCK_RAW instead.
The above option SO_REUSEADDR is now not needed, and remove it:
SOCKET serverIn = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
This works, I can read the data now! Though, Windows now requires the adminstrator rights for my application. Also I do recieve the UDP information in the data which I do not need.
Is there any better method to do this without requiring administrator rights, any possibility to discard the header information in the buffer?
Below is a little program I wrote to demonstrate that IPv4 UDP broadcast can and does work as expected under Windows (i.e. without requiring raw-sockets or Administrator privileges).
Run it with the command line argument "server" and it will send out one broadcast UDP packet per second.
Then also run several more instances of the same program, with no command line arguments, to receive the UDP packets and print a line of text to stdout whenever they do. The expected behavior should look like this:
As for why it's not working for you -- one possible guess is that your UDP-packet-sending program is actually sending out unicast UDP packets rather than broadcast. If that's the case, then I would expect that only one client program would receive packets (even if multiple clients are bound to the same port). A network trace tool like Wireshark might be able to help you determine if the UDP packets being sent are broadcast or unicast.
Anyway, here's the code:
#include <stdio.h>
#include <ws2tcpip.h>
#pragma comment(lib,"WS2_32")
static int BindUDPSocket(SOCKET sock, unsigned short port, bool allowPortSharing)
{
if (sock == INVALID_SOCKET) return -1;
if (allowPortSharing)
{
const BOOL trueValue = true;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &trueValue, sizeof(trueValue)) < 0) return -1;
}
struct sockaddr_in bindAddr; memset(&bindAddr, 0, sizeof(bindAddr));
bindAddr.sin_family = AF_INET;
bindAddr.sin_addr.s_addr = INADDR_ANY; // aka 0.0.0.0
bindAddr.sin_port = htons(port);
return bind(sock, (struct sockaddr *) &bindAddr, sizeof(bindAddr));
}
int main(int argc, char ** argv)
{
WSADATA data;
WORD version = MAKEWORD(2, 2);
(void) WSAStartup(version, &data);
const unsigned short TEST_PORT = 12345;
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock<0) {printf("socket() failed\n"); exit(10);}
if ((argc > 1)&&(strcmp(argv[1], "server") == 0))
{
if (BindUDPSocket(sock, 0, false)<0) {printf("BindUDPSocket() failed for server\n"); exit(10);}
const BOOL allowBroadcast = true;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char *) &allowBroadcast, sizeof(allowBroadcast)) < 0)
{
printf("setsockopt(SO_BROADCAST) failed\n");
exit(10);
}
const char buf[] = {0x01, 0x02, 0x03, 0x04}; // dummy data
struct sockaddr_in toAddr; memset(&toAddr, 0, sizeof(toAddr));
toAddr.sin_family = AF_INET;
toAddr.sin_addr.s_addr = INADDR_BROADCAST; // aka 255.255.255.255
toAddr.sin_port = htons(TEST_PORT);
printf("Sending outgoing broadcast UDP sockets on port %u, once per second\n", TEST_PORT);
while(true)
{
if (sendto(sock, buf, sizeof(buf), 0, (const sockaddr *) &toAddr, sizeof(toAddr)) == sizeof(buf))
{
printf("Sent %zu bytes of broadcast UDP data\n", sizeof(buf));
}
else printf("sendto() failed!\n");
Sleep(1000); // wait 1 second
}
}
else
{
if (BindUDPSocket(sock, TEST_PORT, true)<0) {printf("BindUDPSocket() failed for client\n"); exit(10);}
printf("Waiting to receive incoming broadcast UDP sockets on port %u\n", TEST_PORT);
while(true)
{
char buf[1024];
const int ret = recv(sock, buf, sizeof(buf), 0L);
printf("Received %i bytes of incoming UDP data\n", ret);
}
}
}

forwarding message between clients with a server in middle

I want to take a message from one client and send it to the other with a server in middle.
I use the select function to make several connections to the server possible but here is the problem:
I store the socket descriptor sock in Queue[pq] using dup and it's working. the sock = 4 & Queue[0] = 5. now I need to take the other client's socket descriptor, and again I store it in Queue. the values of Queue for Client(2) equals to Queue[0] = 5 , Queue[1] = 7 but for the first client it's still Queue[0] = 5 and Queue[1] = 0 it means the code for first client doesn't have access to the second client's socket descriptor and i cant forward it to the other client using his socket descriptor with send() and client 3 has the the first 2 client's socket descriptor but the first 2 client doesn't have the third one's socket descriptor.
I think that's because select() use different memory address for the values for each client just like sock which has different values for each connection.
how I can solve this problem? how the clients can access each other's socket descriptor?
the code:
Global Values:
int tcpfd, udpfd, Sock, nready, maxfdp1;
int Queue[64];
int pq = -1;
int max(int x, int y) {
if (x > y)
return x;
else
return y;
}
int main(){
pid_t childpid;
fd_set rset;
ssize_t n;
socklen_t len;
const int on = 1;
struct sockaddr_in cliaddr, servaddr;
void sig_chld(int);
/* create listening TCP socket */
tcpfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("192.168.1.5");
servaddr.sin_port = htons(PORT);
// binding server addr structure to tcpfd
bind(tcpfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
listen(tcpfd, 10);
// clear the descriptor set
// get maxfd
maxfdp1 = max(tcpfd, udpfd) + 1;
for (;;) {
// set tcpfd and udpfd in readset
FD_ZERO(&rset);
FD_SET(tcpfd, &rset);
// select the ready descriptor
nready = select(maxfdp1, &rset, NULL, NULL, NULL);
// if tcp socket is readable then handle
// it by accepting the connection
if (FD_ISSET(tcpfd, &rset)){
len = sizeof(cliaddr);
Sock = accept(tcpfd, (struct sockaddr*)&cliaddr, &len);
pq++;
Queue[pq] = dup(Sock);
printf("%d\n",Sock);
if ((childpid = fork()) == 0) {
Access_Request();
while(1) { //rest of the code
}

Why is my C Socket client failing to receive data and it is failing with an error code of 104. Some code is also not being execute

I have a very big problem that I have encountered with C. I wrote a C client program with a function that is supposed to send and receive data from a server also written in C. But it throws an error. 104. Below is the code for the function.
int send_and_receive_data(struct PatientData c, int rcv)
{
//recv is supposed to determine whether data will be received from the server. it's an integer that can either be 1 or 0
if (rcv)
{
/*create socket*/
int network_socket;
network_socket = socket(AF_INET,SOCK_STREAM,0);
//specify an address for the socket
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
int connection_status = connect(network_socket,(struct sockaddr *) &server_address, sizeof(server_address));
// check for error with the connection
if(connection_status == -1){
printf("There was an error making a connection to the remote socket\n\n");
}
//send data to the server
if(send(network_socket,&c,sizeof(c),0) < 0){
puts("Send Failed\n");
}
else
{
//puts("Data sent\n");
}
if(recv(network_socket,&s_results,sizeof(s_results),0) < 0)
{
printf("Receive Failed %d\n",errno);
printf("Sara Nakamya 2019-01-01 F Mary\n");
}
else
{
// output the received data
puts("Receive successful");
printf("%s %s %s %s\n",s_results.patient_name,s_results.patient_date,s_results.patient_category,s_results.patient_gender);
}
// and then close the socket
close(network_socket);
}
else
{
/*create socket*/
int network_socket;
network_socket = socket(AF_INET,SOCK_STREAM,0);
//specify an address for the socket
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
int connection_status = connect(network_socket,(struct sockaddr *) &server_address, sizeof(server_address));
// check for error with the connection
if(connection_status == -1){
printf("There was an error making a connection to the remote socket\n\n");
}
//send data to the server
if(send(network_socket,&c,sizeof(c),0) < 0){
puts("Send Failed\n");
}
else
{
puts("Data sent\n");
}
// and then close the socket
close(network_socket);
}
return 0;
}
The function sends data to the server and also receives data on the same connection. Now my problem is that the recv() function call always fails with an error code of 104 even when the server has sent data back to the client socket.
Below is the code for the server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
/*
Input Data using commands
Send data to the server
The server writes the data to a text file
Database connection in C
*/
struct patient_data
{
char patient_name[256];
char patient_date[256];
char patient_category[256];
char patient_gender[10];
} s_results;
int main()
{
// create the server socket
int server_socket;
server_socket = socket(AF_INET,SOCK_STREAM,0);
// define the server address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
// bind the socket to our specified IP and port
bind(server_socket, (struct sockaddr*) &server_address,sizeof(server_address));
listen(server_socket,100);
int client_socket;
client_socket = accept(server_socket,NULL,NULL);
struct data
{
int type;
char name[100];
char date_of_identificaton[20];
char category[10];
char gender[5];
} response;
// receive data from server
recv(client_socket,&response,sizeof(response),0);
if(response.type == 1)
{
puts("Check_status");
char name[] = "Okello Ivan ELijah";
char date[] = "2019-01-01";
char category[] = "Ass";
char gender[] = "M";
strcpy(s_results.patient_name,name);
strcpy(s_results.patient_date,date);
strcpy(s_results.patient_category,category);
strcpy(s_results.patient_gender,gender);
send(server_socket,&s_results,sizeof(s_results),0);
puts("Data sent\n");
printf("%s\n%d\n%s\n",response.name,response.type,response.gender);
}
else
{
puts("Data not sent");
}
// close the socket
close(server_socket);
return 0;
}
The server also does not execute the if statement fully. It just executes the first statement of the if else statement and doesn't execute the others. What could be the problem??
Please help me with this anybody
... even when the server has sent data back to the client socket.
Actually, your server does not send data to the client. You probably intended it with this line in the server:
send(server_socket,&s_results,sizeof(s_results),0);
Only, this is using server_socket which is the listener socket. Instead it should have used client_socket, which is the connected socket. Note that if you would have checked the send call for errors you would have realized that the send has failed too. Thus, better check for errors on all places.

How to troubleshoot socket connection from Asterisk

I wrote a module for asterisk that needs to communicate to a service request information an return it, but for some reason my socket does not connect at all. When I telnet to the service it works fine, but I can not figure out why the it returns a -1 in the module
This is the code in my module
int SocketQuery(char buffer[BUFFSIZE],char *qrystr){
int sock;
struct sockaddr_in eserver;
int sockres = 0;
unsigned char receiving = 1;
memset(sendbuff,0,sizeof(sendbuff));
/* Create the TCP socket */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
ast_log(LOG_ERROR,"Failed to create socket for LCRROUTER");
return -1;
}
/* Construct the server sockaddr_in structure */
memset(&eserver, 0, sizeof(eserver)); /* Clear struct */
eserver.sin_family = AF_INET; /* Internet/IP */
eserver.sin_addr.s_addr = inet_addr(IP); /* IP address */
eserver.sin_port = htons(port); /* server port */
/* Establish connection */
ast_log(LOG_NOTICE,"LCRROUTER - Connection to %s on port %s\n", IP, port);
sockres = connect(sock,
(struct sockaddr *) &eserver,
sizeof(eserver));
if (sockres < 0) {
ast_log(LOG_ERROR,"LCRROUTER - Failed to connect with server on %s:%s. Error Code %d", IP,port,sockres);
return -1;
}
sockres returns -1. Do I miss something?
You can use
tcpdump port YOUR_PORT_HERE -v -s0
In that form it will show you all packets sent via socket.

client socket unable to receive data using poll/select

/* SEND FUNC. */
int mysend(unsigned char *buffer, int len) {
int sock,ret;
int status,flags;
struct sockaddr_in6 servaddr;
int opt = 1;
char *addr = "1101::1";
sock = socket(AF_INET6,SOCK_DGRAM,0);
if (sock < 0)
return -1;
if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
return -1;
flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags|O_NONBLOCK);
servaddr.sin6_family = AF_INET6;
servaddr.sin6_port = htons(61616);
status = inet_pton(AF_INET6, addr, &servaddr.sin6_addr);
if (status <= 0) {
perror("inet_pton");
return -1;
}
/* send message to server */
status = sendto(sock, buffer, len, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (status < 0) {
perror("sendto");
return -1;
}
close(sock);
printf("MESSAGE SENT SUCCESSFULLY\n");
return 0;
}
/* RECEIVE FUNC. */
int myrcv() {
int sock,ret;
int status,len,rx_bytes;
int timeout,nfds =1;
struct sockaddr_in6 servaddr;
struct timeval wait;
unsigned char rxbuff[1024];
char *rcv;
char *addr = "1101::1";
fd_set rd;
struct pollfd *fds;
sock = socket(AF_INET6,SOCK_DGRAM,0);
if (sock < 0)
return -1;
servaddr.sin6_family = AF_INET6;
servaddr.sin6_port = htons(61616);
status = inet_pton(AF_INET6, addr, &servaddr.sin6_addr);
if (status <= 0)
return -1;
bind(sock,(struct sockaddr *)&servaddr,sizeof(servaddr));
timeout = (1* 1000);
wait.tv_sec = 10;
wait.tv_usec = 0;
len = sizeof(servaddr);
fds->fd = sock;
fds->events = POLLIN;
for(;;) {
//FD_ZERO(&rd);
//FD_SET(sock,&rd);
printf("Waiting for data....\n");
ret = poll(fds,nfds,timeout);
//ret = select(1,&rd,NULL,NULL,&wait);
if(ret < 0)
break;
if(fds->revents == 0)
printf("revents 0 %d\n",ret);
if(ret == 0)
continue;
memset(rxbuff,0,1024);
//if(FD_ISSET(sock,&rd)) {
printf("receiving message\n");
rx_bytes = recvfrom(sock,rxbuff,1024,0,(struct sockaddr *)&servaddr,&len);
memcpy(rcv,rxbuff,rx_bytes);
//}
}
close(sock);
return 0;
}
int main()
{
/* call mysend() periodically using sigaction() */
/* create a thread that continuously monitors(calls myrcv()) for incoming data */
return 0;
}
I'm unable to receive the packets from the server, but I could see the packets in the tcpdump output. Above are the sample client code snippets, which tries to receive and send the data from/to the server. The scenario is: the client needs to send data periodically to server and should also be able to receive any data from the server.
I have tried using both poll and select methods but failed to receive. Please let me know if I'm missing anything. Thanks for your support.
The problem you have with receiving is that you need to bind the receiving socket to the local port.
You also have other things that can be improved, like creating a single socket for both sending and receiving and using SO_REUSEADDR on the sending socket (not needed on a write-only socket).
What you should do is:
Create socket
Set socket options
Bind to local address (Use IN6ADDR_ANY_INIT to bind to all interfaces)
Write to server
Poll for reply
Several things:
Your receive function (myrcv) isn't specifying a listen port via the bind() call. That's the most likely problem. Ditto for your send function, although a port is chosen randomly for you.
In you myrcv() function, I don't see where you have actually initialized fds or nfsd prior to calling poll().
Re-opening and closing the socket on each call to mysend() looks problematic. If you are expecting the server to send back to the same client on the same port it received the message on, chances are high you have already closed the socket. You should just open one socket for both sending and receiving. You can share the same socket between your send thread and your receive thread.

Resources