Bool array transfer from server with UDP in C - arrays

I need to create a simple modbus application to transfer data from server to client in Bool type. I created client and server codes for this.
Server side:
int main() {
struct sockaddr_in other_addr;
SOCKET soket, slength=sizeof(other_addr);
bool message[256]={1};
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
exit(EXIT_FAILURE);
}
if ((soket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
exit(EXIT_FAILURE);
}
memset((bool*)&other_addr, 0, sizeof(other_addr));
other_addr.sin_family = AF_INET;
other_addr.sin_port = htons(port);
other_addr.sin_addr.S_un.S_addr = inet_addr(server_addr);
while (1) {
if (sendto(soket1, message, 256, 0, (struct sockaddr*)&other_addr, slength) == -1) {
exit(EXIT_FAILURE);
}
printf("%d\n",message);
printf("%d-%d-%d-%d\n", message[0], message[1], message[2], message[3]);
//closesocket(soket);
//WSACleanup();
}
return 0;
}
Client side:
int ImportedClient()
{
SOCKET soket;
struct sockaddr_in server_addr, other_addr;
int slength=sizeof(other_addr), recv_length;
bool message[256];
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
exit(EXIT_FAILURE);
return 3;
}
if((soket = socket(AF_INET , SOCK_DGRAM , 0 )) == -1)
{
exit(EXIT_FAILURE);
return 2;
}
memset((bool *) &other_addr, 0, sizeof(other_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons( port );
if( bind(soket ,(struct sockaddr *)&server_addr , sizeof(server_addr)) == -1)
{
exit(EXIT_FAILURE);
return 1;
}
fflush(stdout);
memset(message,'0', maxdata);
if ((recv_length = recvfrom(soket, message, 256, 0, (struct sockaddr *) &other_addr, &slength)) == -1)
{
exit(EXIT_FAILURE);
return 5;
}
bool x=message[0];
bool y=message[1];
bool z=message[2];
bool k=message[3];
closesocket(soket);
WSACleanup();
return 0;
}
When I start data transfer, 'printf ("% d \ n", message);' code gives an output '6422012'. However, when printing the elements of the message array one by one with the printf code, it prints correctly. I cannot get the correct data individually or collectively from the client side. The output of client side reads true directly. As I understand it, when trying to read from the client, it directly accepts true because 6422012 data transfers to the client. Where do I need to fix it so that it can be read correctly by the client, or how can I get it if I need to buy one by one?
Note: I've also tried sending x1, x2, x3 one by one, but again when I print them, there are 6... numbers.
Please help me :((

According to the given code, message is an array.
printf("%d", message); will interpret the message variable as a decimal integer, says "%d". As message is an array, it is then the address of the first element of that array. "%d" will interpret this address (not the value) as an integer. So your code is printing the address in memory as a decimal number!
If you want to print the values of the array, printf cannot do it for you, unless...:
for (int i = 0; i < 256; i ++) {
printf("%d", message[i] ? 1 : 0); /* bool interpretation */
}
That should do the trick.
Look at the following working example as a reply:
https://gist.github.com/be1/7f4976207cb8e2c7faf96b3aa3de6dd8
P.S.: don't use (bool*) cast on other_addr or server_addr since they are not of type bool.

Related

How to send data from python to C using sockets (unix)

I'm trying to create a unix socket to allow some of my c code to talk to some of my python code. The C code is acting as the socket and the python as the client. So far I have been able to create the socket and connect the client to it, but i'm either unable to send data through it or receive data through it in either direction (I can't tell where the problem is).
I've tried changing the encoding of the data i'm sending, I've tried sending the data over and over again in case it's a timing issue, these don't appear to be the problem.
C server code:
int makeSocket(struct sockaddr_un * addr, char* path){
unlink(path);
int sock;
//struct sockaddr_un addr;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
fcntl(sock, F_SETFL, O_NONBLOCK);
addr->sun_family = AF_UNIX;
strncpy(addr->sun_path, path, sizeof(addr->sun_path));
size_t size = (offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path));
if (bind(sock, (struct sockaddr*) addr, size) < 0){
printf("failed to bind\n");
}
listen(sock, 5);
return sock;
}
//this isn't actually here but just so you can see it being created, its a global int
globSock = makeSocket("socket.soc");
Then in an idle callback:
f (!connected){
int len = sizeof(addr);
if (connection = accept(globSock, (struct sockaddr*) &addr, &len) < 0){
printf("Can't listen\n");
} else {
printf("connected\n");
send(connection, "HI", strlen("HI"), 0);
connected = 1;
}
} else {
int rc;
if (!recevd && ((rc = recv(connection,buffer,BUFFERSIZE,0)) < 0)){
printf("nope %s\n", buffer);
} else if (rc == 0) {
connected = 0;
printf("%s\n", buffer);
} else {
recevd = 1;
printf("%s\n", buffer);
}
}
connected and recevd are flag variables and buffer is an array of char (buffer size is 100, just a #define)
Python client:
# -*- coding: utf-8 -*-
import socket
import os
print("Connecting...")
if os.path.exists("socket.soc"):
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
client.connect("socket.soc")
print("Ready.")
print("Ctrl-C to quit.")
print("Sending 'DONE' shuts down the server and quits.")
while True:
try:
x = input("> ")
if "" != x:
print("SEND:", x)
client.send(x.encode('utf-8'))
if "DONE" == x:
print("Shutting down.")
break
except KeyboardInterrupt as k:
print("Shutting down.")
client.close()
break
else:
print("Couldn't Connect!")
print("Done")
On the C side it repeatedly prints "nope" (the I haven't received anything yet print) and on the python side it simply asks for input, you can give it the message, it'll 'send' it and then ask for another etc...
The issue was in
if (connection = accept(globSock, (struct sockaddr*) &addr, &len) < 0){
it was saving the comparison in connection rather than the actual socket the solution was:
if ((connection = accept(globSock, (struct sockaddr*) &addr, &len)) < 0){

UDP socket: invalid argument error in sendto

I'm trying to write a simple UDP socket client-server program. The client machine is supposed to send a string to the server, that will answer with an ACK message.
Here's the implementation of the client side:
int main() {
message_send('L');
return EXIT_SUCCESS;
}
int message_send(char code) {
int sockfd;
ssize_t n;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr;
// Create an UDP socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket");
return -1;
}
// Setup the socket
memset((void *) &servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = (in_port_t) htonl(SERV_PORT);
if (inet_pton(AF_INET, SERVIP, &servaddr.sin_addr) <= 0) {
fprintf(stderr, "Error in inet_pton for %s\n", SERVIP);
exit(1);
}
// Send a test string
char *test = malloc(MAXLINE);
snprintf(test, MAXLINE, "SENDING:%c", code);
if (sendto(sockfd, &test, sizeof(test), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
perror("sendto");
return -1;
}
// Get an answer from the server
n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
if (n < 0) {
perror("recvfrom");
exit(1);
} else if (n > 0) {
recvline[n] = 0; // Add ending character
if (fputs(recvline, stdout) == EOF) { // Print the received message in stdout
perror("fputs");
return -1;
}
}
return 0;
}
If I run this (whether the server machine is running or not) I get the following error:
sendto: Invalid argument
Why am I getting this error?
The most likely cause of the problem is the line
servaddr.sin_port = (in_port_t) htonl(SERV_PORT);
I'm guessing that gives you a bad port number (i.e. it will give you port 0 on a little endian machine). Port numbers are 16-bit, so you should be using htons.
Also, passing &test and sizeof(test) to sendto will send the pointer value over the network. To send the string, you need to use test and strlen(test)+1.

how to send data from array to pointer variable and back from pointer variable to array?

#include "MAIN.h"
#include "xcpip_callbacks.h"
typedef unsigned _int16 uint16;
typedef unsigned _int8 uint8;
uint16 port = 18017;
void XcpApp_IpTransmit( uint16 port, Xcp_StatePtr8 pBytes, uint16 numBytes )
{
WSADATA wsa;
SOCKET s;
uint8 bytes_recieved;
uint8 send_data[1024],recv_data[1024];
struct sockaddr_in server; // creating a socket address structure: structure contains ip address and port number
printf("Initializing Winsock\n");
if(WSAStartup(MAKEWORD(2,2), &wsa)!=0)
{
printf("Failed Error Code: %d", WSAGetLastError());
return 1;
}
printf("Initialised\n");
//int sock, bytes_recieved;
//char send_data[1024],recv_data[1024];
//struct hostent *host;
//struct sockaddr_in server_addr;
//host = gethostbyname("127.0.0.1");
/*if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket");
exit(1);
}*/
//CREATING a SOCKET
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("Could not Create Socket\n");
return 0;
}
printf("Socket Created\n");
server.sin_addr.s_addr = inet_addr("192.168.0.1");
server.sin_family = AF_INET;
server.sin_port = htons("port");
//Connect to a remote server
if(connect(s, (struct sockaddr *)&server, sizeof(server))<0)
{
puts("Connect Error\n");
return 1;
}
puts("Connected\n");
//SENDING a data
/* bzero(&(server_addr.sin_zero),8);
if (connect(sock, (struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1)
{
perror("Connect");
exit(1);
}*/
while(1)
{
/*
s- socket
recv_data - receive data buffer and size of it (1024)
*/
bytes_recieved=recv(s,recv_data,1024,0);
recv_data[bytes_recieved] = '\0';
if(strcmp(recv_data , "q") == 0 || strcmp(recv_data , "Q") == 0)
{
close(s);
break;
}
else
printf("\nRecieved data = %s " , recv_data);
/*
port For TCP: the port which listened for the connection which
was used to transmit the data. Note that this may not be
the same as the port which actually transmitted the data.
For UDP: the port which transmitted the data.
numTxBytes The number of bytes which were transmitted during the
latest call to XcpApp_IpTransmit(). For TCP, this may
be less than the total number of bytes which were supplied
to XcpApp_IpTransmit().*/
XcpIp_TxCallback(uint16 port, uint16 numTxBytes );
printf("\nSEND (q or Q to quit) : ");
gets(send_data);
if (strcmp(send_data , "q") != 0 && strcmp(send_data , "Q") != 0)
send(s,send_data,strlen(send_data), 0);
else
{
send(s,send_data,strlen(send_data), 0);
/*
chunkLen : The number of bytes at pChunkData.
pChunkData : The payload of the received IP frame. The caller does not
need to interpret the payload: the entire payload should be
passed to XcpIp_RxCallback().
The caller can discard this data after the function returns.
port For TCP: the port which listened for the connection which
received the data. Note that this may not be the same as
the port which actually received the data.
For UDP: the port which received the data. */
XcpIp_RxCallback(uint16 chunkLen, uint8* pChunkData, uint16 port);
closesocket(s);
WSACleanup();
break;
}
}
}
I have created a TCP Layer for sending and receiving the data on the specific port and calling some specific XCP protocol to perform some activity. I have created a socket and specified the port number and ip address to send and receive data. I am receiving some data on the recv_data[1024]; I can send data from the send_data[1024];
I need some help for :
Before writing or sending that data: I should send the data from send_data[1024] to Xcp_StatePtr8 pBytes (pointer points to memory in an address space). Later I have to write data from Xcp_StatePtr8 pBytes to recv_data[1024];
Could anyone please suggest me some ideas ??
You can use memcpy to write the data from an array to a pointer and vice versa like this example I created below:
#include <stdio.h>
#include <cstring>
#define MAX_SIZE 20
int main()
{
int anTest[MAX_SIZE] = {200, 200, 200, 200};
int anTest2[MAX_SIZE];
int* pnTest = new int[MAX_SIZE];
// Initializing array and pointer to 0
memset(anTest2, 0, sizeof(anTest2));
memset(pnTest, 0, sizeof(pnTest));
//Outputting anTest values and exiting loop when
//an element contains 0, just because.
puts("anTest values: ");
for(int nIndex = 0; nIndex < MAX_SIZE; nIndex++)
{
if (0 == anTest[nIndex])
{
break;
}
printf("%d: %d\n", nIndex, anTest[nIndex]);
}
//Copying array to pointer
memcpy(pnTest, anTest, MAX_SIZE * sizeof(int));
//Copying pointer to array
memcpy(anTest2, pnTest, MAX_SIZE * sizeof(int));
//Outputting anTest2 values and exiting loop when
//an element contains 0, just because.
puts("\nanTest2 values: ");
for(int nIndex = 0; nIndex < MAX_SIZE; nIndex++)
{
if (0 == anTest2[nIndex])
{
break;
}
printf("%d: %d\n", nIndex, anTest2[nIndex]);
}
//Deleting pointer since it's no longer needed.
delete pnTest;
pnTest = NULL;
return 0;
}
[EDIT] I forgot to add code to prove that it works (I always check my code by walking through the code instead of outputting the values lol). I edited my code to include printing the output values.

Multi session chat server in C

I am trying to write a multi session chat server in C. I host the server from one terminal and telnet to it from other terminals.
Using ubuntu 13.04 on VMWare player.
What happens is this:
I'm incrementing a loop from 3 onward to fdmax, to accept new connections using sd ( the listener) and newsd represents the new socket descriptor.
When I print 'hi' in one window, it prints in ALL windows including the one I typed in. Plus, a lot of random junk keeps appearing.
I want only what I type to appear(how do i get rid of the junk>), and in all the windows except the one I typed it in!
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netdb.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<sys/select.h>
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET)
{
return &(((struct sockaddr_in*) sa)->sin_addr);
}
return &(((struct sockaddr_in6*) sa)->sin6_addr);
}
int main(int argc, char **argv)
{
//ptr used for traversal, serv used for the linked list of struct addinfos , hints for the getaddrinfo function
struct addrinfo *ptr, hints, *serv;
int max_cli, dat, x, i;
struct sockaddr_storage cli_addr;
socklen_t addr_size;
char cli_ip[INET_ADDRSTRLEN];
char inc[256]; //one command line is 80 characters
memset(inc, 0, strlen(inc));
int sd, newsd;
fd_set master;
fd_set read_fds;
char value[256];
FD_ZERO(&master);
FD_ZERO(&read_fds);
//argv[1]-server ip argv[2]-server port argv[3]-maximum client number
int fdmax;
int opt = 1;
/*if(argc!=4)
{
printf("Please re-enter data. Data insufficient\n");
exit(1);
}
if(atoi(argv[2])<1025)
{
printf("Reserved port. Please try again\n");
exit(1);
}*/
max_cli = atoi(argv[3]);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
/* Verify the inputs and generate linked list of possible IPs to use*/
if (sd = getaddrinfo(argv[1], argv[2], &hints, &serv))
{
fprintf(stderr, "Error calling getaddrinfo %s\n", gai_strerror(sd));
exit(1);
}
for (ptr = serv; ptr != NULL ; ptr = ptr->ai_next)
{
void *addr;
if (ptr->ai_family == AF_INET)
{
struct sockaddr_in *ipv4 = (struct sockaddr_in *) ptr->ai_addr;
addr = &(ipv4->sin_addr);
}
inet_ntop(ptr->ai_family, addr, value, sizeof value);
//printf("%s\n",value);
//Form connection with one of the IP addresses
sd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (sd < 0)
continue;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt);
if (bind(sd, ptr->ai_addr, ptr->ai_addrlen) < 0)
{
close(sd);
continue;
}
break; //Indicates one working socket found and bound
} //end for
if (ptr == NULL )
{
fprintf(stderr, "Bind failed\n");
exit(2);
}
freeaddrinfo(serv);
if (listen(sd, 15) == -1)
{
printf("Error occurred while listening\n");
exit(3);
}
/* Socket found, bound and now listening for active connections*/
FD_SET(sd, &master);
fdmax = sd; //Latest active socket descriptor
while (1)
{
read_fds = master; //Copy the master list so that the original list doesn't get damaged
if (select(fdmax + 1, &read_fds, NULL, NULL, NULL ) == -1)
{
perror("Select failed.\n");
exit(4);
}
for (i = 3; i <= fdmax; i++)
{
//printf("i");
//printf("entered for loop\n");
if (FD_ISSET(i,&read_fds)) //new connection->false, existing one->true
{
// printf("Started reading descriptors!\n");
if (i == sd) //primary connection,exists, accept new file descriptor
{ //printf("Read first connection!\n");
addr_size = sizeof cli_addr;
newsd = accept(sd, (struct sockaddr *) &cli_addr, &addr_size);
printf("Accepted new connection socket %d\n", newsd);
FD_SET(newsd, &master);
if (newsd == -1)
{
perror("accept");
}
if (newsd > fdmax)
{
fdmax = newsd;
}
printf("%d %d\n", newsd, fdmax);
continue;
}
else if (i != sd) //existing connection, so accept data
{
if (dat = recv(i, &inc, sizeof inc, 0) <= 0)
{
if (dat == 0)
{
printf(" Socket %d has quit the chatroom", i);
}
if (dat < 0)
{
perror("Error on Receive");
}
// char *s=&inc;
//printf("%d\n %s",dat);
close(i);
FD_CLR(i, &master);
}
//Nothing wrong with the input from client i. Broadcast!
else
{
for (x = 3; x <= fdmax; x++)
{
if (FD_ISSET(x,&master))
{
if (x != sd)
{
//send(x,&inc,sizeof inc,0);
if (send(x, &inc, sizeof inc, 0) < 0)
{
perror("Send");
}
}
}
}
}
}
}
/*else// new connection
{ break;
printf("SERVERBOT: new connection from %s on socket %d\n",inet_ntop(cli_addr.ss_family,get_in_addr((struct sockaddr*)&cli_addr),cli_ip, INET6_ADDRSTRLEN),newsd);
}////change this to 'username' has joined the room*/
}
}
return 0;
}
First of all, when you send received data, you use sizeof operator, which gives you total size of array. You should send just as many bytes as you received, which will often be less. Use return value of recv to know how many bytes were actually received. In general, C arrays do not have dynamic size, you have to keep track of that yourself.
Then about garbage, you probably print buffer contents without terminating '\0' character. So, either add that (make sure there is the 1 byte of extra space in the buffer!) before printing or using other string functions, or use a printing function which accepts maximum size of string in case that terminating nul is missing.
for a start your send must use dat as length not sizeof(inc)

Strange behaviour in a simple Client/Server Countdown C Application

I am trying to implement a simple countdown application in C using UDP sockets.
I have a very strange problem with the server part of the application: it should receive a number from a client and then send different numbers for the countdown. So if, for example, a user types 5 in the client, then the server should receive 5 and send 4, 3, 2, 1 and 0 to the client. Here's my code:
#define BUFFERSIZE 512
#define PORT 55123
void ClearWinSock()
{
#if defined WIN32
WSACleanup();
#endif
}
int main()
{
#if defined WIN32
WSADATA wsaData;
WORD wVersionRequested;
wVersionRequested = MAKEWORD(2, 2);
if(WSAStartup(wVersionRequested, &wsaData) != 0)
{
printf("Error: unable to initialize the socket!\n");
return -1;
}
#endif
int mainSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(mainSocket < 0)
{
printf( "Error: unable to create the socket!\n");
ClearWinSock();
return -1;
}
struct sockaddr_in serverSockAddrIn;
memset(&serverSockAddrIn, 0, sizeof(serverSockAddrIn));
serverSockAddrIn.sin_family = AF_INET;
serverSockAddrIn.sin_port = htons(PORT);
serverSockAddrIn.sin_addr.s_addr = inet_addr("127.0.0.1");
if(bind(mainSocket, (struct sockaddr*) &serverSockAddrIn, sizeof(serverSockAddrIn)) < 0)
{
fprintf(stderr, "Error: unable to bind the socket!\n");
ClearWinSock();
return -1;
}
char buffer[BUFFERSIZE];
struct sockaddr_in clientAddress;
unsigned int clientAddressLength;
int recvMessageSize;
while(1)
{
clientAddressLength = sizeof(clientAddress);
recvMessageSize = recvfrom(mainSocket, buffer, BUFFERSIZE, 0, (struct sockaddr*) &clientAddress, &clientAddressLength);
int countdownValue;
sscanf(buffer, "%d", &countdownValue);
printf("\nNumber received: %d\n", countdownValue);
int index;
for(index = countdownValue - 1; index >= 0; --index)
{
itoa(index, buffer, 10);
int outputStringLength = strlen(buffer);
if(sendto(mainSocket, buffer, outputStringLength, 0, (struct sockaddr*) &clientAddress, sizeof(clientAddress)) != outputStringLength)
{
printf("Error: unable to send the message!");
}
}
}
ClearWinSock();
return 0;
}
Now the problem is that if I, for example, send the number 5 from the client, sometimes the server works correctly and sometimes it says "Number received: 5", doesn't send anything and then it says "Number received: 0" for 5 times.
I think I am doing something wrong in using the sockets. Or maybe it's something which involves cleaning the buffer, don't know! I can't reproduce the error because with the same input sometimes it acts in a way and sometimes in the other.
Are both your client and your server both listening on the same port? If so, you might want to consider having them listen on different ports (e.g. client sends to X and listens to port Y; server sends to port Y and listens to port X) so that they don't interfere with each other or accidentally receive their own sent-packets when both client and server are running on the same host.
Alternatively, you can instruct both client and server to share the same port by always executing the following code before calling bind():
const int trueValue = 1;
setsockopt(mainSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) &trueValue, sizeof(trueValue));

Resources