Bool array transfer from client with UDP in C - arrays

I need to create a simple modbus application that will transfer data in bool type. I created client and server codes for this.
Client side:
int Client(bool message[8])
{
struct sockaddr_in si_other;
int s, slen=sizeof(si_other);
bool buf[BUFLEN];
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
exit(EXIT_FAILURE);
return 1;
}
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
{
exit(EXIT_FAILURE);
return 2;
}
memset((bool *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
si_other.sin_addr.S_un.S_addr = inet_addr(SERVER);
if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
exit(EXIT_FAILURE);
return 3;
}
// closesocket(s);
// WSACleanup();
return 0;
}
Server side:
int main()
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen , recv_len;
bool buf[BUFLEN];
WSADATA wsa;
slen = sizeof(si_other) ;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( PORT );
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
while(1)
{
printf("Waiting for data...\n");
fflush(stdout);
memset(buf,'0', BUFLEN);
if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
for (int i=0; i<=7; i++) {
printf("%d", buf[i]);
}
printf("Data: %d\n" , buf);
printf("%s-%s-%s\n",buf[0],buf[1],buf[2]); //When I run this code, it works just like the code with 'for' and gives an error.
if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
}
closesocket(s);
WSACleanup();
return 0;
}
When I run the application, the data transfer is not correct. For example, when I send data as '101010', it transmits '100000'; If send data as '110101', it transmits '110000' or if send it as '011111', it transmits '000000'. In other words, in order to read a data with a value of '1' correctly, all the values before that data must be '1'.
When I remove the 'for' part in the code and try to read the whole buf directly ( printf("Data: %d\n" , buf) ) , it reads '6421972' data. Even if I change the data, this number does not change. What can I do to overcome this problem?

In your client, strlen(message) will count chars until the first '0'encoutered. So your sent bool array never will be of length 8.
Your client must then take the buffer length too in parameter to fix this.
If your buffer is a true C array (not an allocated pointer) then sizeof statement can give the length. But if you use a malloc'd pointer for buf, sizeof statement will always return 8, never less, never more (in 64 bit systems), that is the size of a pointer only.
In short, always keep a length integer alongside with a buffer.

Related

Server client using select()

I want to implement a server-client monothreaded, using select();
For the server part, I took the code from http://www.binarytides.com/code-tcp-socket-server-winsock/ and for the client, the site does not provide some code, they use netcat to simulate the client. So, for the client, I am using this code:-
#include <stdio.h>
#include <winsock2.h
#pragma comment(lib,"ws2_32.lib")
int main(void) {
struct sockaddr_in si_other;
int s, slen=sizeof(si_other);
char buf[512];
char message[512];
WSADATA wsa;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//create socket
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
{
printf("socket() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//setup address structure
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(8888);
si_other.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//start communication
while(1)
{
printf("Enter message : ");
gets(message);
//send the message
if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//receive a reply and print it
//clear the buffer by filling null, it might have previously received data
memset(buf,'\0', BUFLEN);
//try to receive some data, this is a blocking call
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts(buf);
}
closesocket(s);
WSACleanup();
return 0;
}
Even the server and the client have the same port, the client always returns -1 meaning that he don't send any message to server. Can someone please tell me what I am doing wrong here? Any tips would be appreciated.
Thanks.

Connection Refused even after adding a new Firewall rule

I am trying to connect to my local UNIX server i made from another remote device. the Server is up and listening to the port i specified. i also added a new firewall rule to open that port but still my client cannot connect. it shows ERROR CONNECTION REFUSED
here is my server code
int main() {
int fd, i,svclient,rval,msg;
int clients[10], num_clients;
fd_set read_set,write_set;
char buf[100];
struct sockaddr_in addr;
if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
bzero((char *) &addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(4001);
//strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
//strcpy(addr.sun_path, NAME);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("bind error");
exit(-1);
}
printf("Bind complet...\n");
if (listen(fd, 20) == -1) {
perror("listen error");
exit(-1);
}
num_clients = 0;
int size = sizeof(fd);
while (1) {
int clientfd;
struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr);
FD_ZERO(&read_set);
FD_SET(fd, &read_set);
for (i = 0; i < num_clients; i++) { //at first this part will not excute
FD_SET(clients[i], &read_set);
}
select(fd + num_clients + 1, &read_set, NULL, NULL, NULL);
if (FD_ISSET(fd, &read_set)) {
if ( (clients[num_clients++] = accept(fd,(struct sockaddr*)&client_addr,&addrlen)) == -1) {
perror("accept error");
continue;
}
/*printf("incoming message..................... !\n \n");*/
printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
}
for (i = 0; i < num_clients; i++) {
if (FD_ISSET(clients[i], &read_set)) {
msg = read(clients[i], buf, sizeof(buf));
if(msg > 0){
buf[msg] = 0;
int savedclnt = clients[i];
printf("%s \n \n", buf);
/*for(int p=0;p<num_clients;p++)
{
if( clients[p]!= savedclnt){
write(clients[p],buf,msg);
}
}*/
}
}
}
}
}
and my client
int main( )
{
struct uci_context *uci;
uci = uci_init();
int sockfd;
int ret;
struct sockaddr_in dest;
struct addrinfo hint, *res = NULL;
struct hostent *host;
char *hostip;
char *string;
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
puts("Unble to create socket");
exit(1);
}
hostip = ucix_get_option(uci, "pack_mon", "pack_monitoring", "address");
string = ucix_get_option(uci, "pack_mon", "pack_monitoring", "port");
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(atoi(string));
memset(&hint, '\0', sizeof hint);
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
printf(" %s- %s\n", hostip, string );
if(isdigit(hostip[0])){
ret = getaddrinfo(hostip, NULL, &hint, &res);// this is more efficient than inet_addr
if (ret) {
exit(1);
}
}else if( (host = gethostbyname(hostip)) != 0){
memcpy((char*)&dest.sin_addr , (char*)host->h_addr , (sizeof dest.sin_addr)+1);
}else{
exit(1);
printf("cannot resolve ip address");
}
if ( connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0 )
{
perror("ERROR Connecting" );
exit(1);
}else{
printf("Port number %s is open.....\n",string);
}
char *message;
message = "help";
write(sockfd,message,strlen(message));
close(sockfd);
freeaddrinfo(res);
return 0;
}
FIREWALL RULE
sudo iptables -I INPUT -p tcp --dport 4001 -j ACCEPT
Error is :
192.168.10.155- 4001
ERROR Connecting: Connection refused
and this logs are coming from this codes :
printf(" %s- %s\n", hostip, string );
perror("ERROR Connecting");
exit(1);
Your client has no code to specify the IP address it wants to connect to. All the code that could do that has been commented out.
Update: Now your bug is here:
strncpy((char*)&dest.sin_addr , (char*)host->h_addr , sizeof dest.sin_addr);
The strncpy function is only suitable for C-style strings. You need to use memcpy or something similar. This will only copy part of the IP address if any octet other than its last one (in network byte order) is zero.
Update: Now your bug is here:
printf("%d\n", connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0);
perror("hmmmm" );
exit(1);
This calls connect, then calls printf and then calls perror. The problem is, the call to printf can modify errno even if it succeeds. Thus your call to perror can print a totally irrelevant error message.

Error connection to remote server in socket programming using c

It is a sample code where i have tried to pass a request to server and get me the desired data.
But my connect to remote server code is not working as i thought.
if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
puts("Connected");
I don't know why value of the condition is getting below zero.Why connection is not getting done?
Full code:
/*
Create a TCP socket
*/
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
char *message , server_reply[2000];
int recv_size;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
server.sin_addr.s_addr = inet_addr("74.125.235.20");
server.sin_family = AF_INET;
server.sin_port = htons( 80 );
//Connect to remote server
if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
puts("Connected");
//Send some data
message = "GET / HTTP/1.1\r\n\r\n";
if( send(s , message , strlen(message) , 0) < 0)
{
puts("Send failed");
return 1;
}
puts("Data Send\n");
//Receive a reply from the server
if((recv_size = recv(s , server_reply , 2000 , 0)) == SOCKET_ERROR)
{
puts("recv failed");
}
puts("Reply received\n");
//Add a NULL terminating character to make it a proper string before printing
server_reply[recv_size] = '\0';
puts(server_reply);
closesocket(s);
WSACleanup();
return 0;
}
You need to initalize the whole sockaddr_in to zero before assigning to it.
memset( &server, 0, sizeof(server) );
server.sin_addr.s_addr = inet_addr("74.125.235.20");
server.sin_family = AF_INET;
server.sin_port = htons( 80 );
I copied your code and tried it out and it seemed to work, maybe you have a firewall that is interfering.
BTW I changed your inet_addr call to
InetPtonA( AF_INET, "74.125.235.20", &server.sin_addr.s_addr );

TCP Server Crash

I am just wondering why this crashes when a client connects?? Its supposed to be a simple TCP server that when the client connects and sends a string, the server responds with the number of A's in the string. The server crashes as soon as the client types a letter in.
#include<io.h>
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET s , new_socket, master;
struct sockaddr_in server , address;
int c, valread;
char *message = "Welcome to Marshall's TCP Server!!";
int MAXRECV = 1024;
char *buffer;
char AmmtA = 'a';
char AmmtB = 'A';
int count = 0, x;
fd_set readfds;
buffer = (char*) malloc((MAXRECV + 1) * sizeof(char));
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 9000 );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//Listen to incoming connections
listen(s , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while( (new_socket = accept(s , (struct sockaddr *)&address, &c)) != INVALID_SOCKET )
{
puts("Connection accepted");
send(new_socket , message , strlen(message) , 0);
valread = recv( new_socket , buffer, MAXRECV, 0);
if( valread == SOCKET_ERROR)
{
int error_code = WSAGetLastError();
if(error_code == WSAECONNRESET)
{
//Somebody disconnected , get his details and print
printf("Host disconnected unexpectedly , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
closesocket( s );
}
else
{
printf("recv failed with error code : %d" , error_code);
}
}
if ( valread == 0)
{
//Somebody disconnected , get his details and print
printf("Host disconnected , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
closesocket( s );
}
else
{
for (x = 0; buffer[x] != '\0'; x++) {
if (buffer[x] == AmmtA || buffer[x] == AmmtB)
count++;
}
char feedback[150];
sprintf(feedback, "There is %d A's in your string", count);
feedback[MAXRECV] = '\0';
printf("%s:%d - %s \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port), buffer);
send( s , feedback , MAXRECV , 0 );
}
free(buffer);
}
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d" , WSAGetLastError());
return 1;
}
closesocket(s);
WSACleanup();
return 0;
}
10057 - WSAENOTCONN - Socket is not connected.
The send call is correct and it uses new_socket. But the recv call uses socket/sd "s". The recv call should also use new_socket.
The error 10057 is returned because s is only bound to the local end point and not connected with the remote end whereas the new socket returned by the accept connected to the remote end.
for (x = 0; buffer[x] != '\0'; x++) {
if (buffer[x] == AmmtA || buffer[x] == AmmtB)
count++;
}
Why are you comparing buffer[x] to 0. There's no special reason any particular entry in the buffer should be zero, and this can easily read off the end of the buffer. Perhaps you think buffer contains a string. But it doesn't. It contains whatever you read from the socket, and it has no special format or terminator.
Fortunately, you do know the number of bytes you read. You stored that in valread, so you want:
for (x = 0; x < valread; x++) {

TCP Sockets, "cannot assign requested address" and " Transport endpoint is already connected" errors

I am new to working with TCP sockets and I do not understand the errors I am getting when running my programs. I have two programs that when run simultaneous I would like to be able to pass messages between. The initial message gets through but then when trying to return another message I get two errors. When I run my first program the output is:
Input Message: hello
Waiting for incoming connections...
Connection accepted
Message Sent
Connection error: Transport endpoint is already connected
Now running the other program simultaneously gives:
Input Message: Hello Back
Connected
Message received
hello
Bind error: Cannot assign requested address
If anyone could explain these "cannot assign requested address" and " Transport endpoint is already connected" errors I would greatly appreciate it!! Thanks!
The first program is:
int main(int argc, char *argv[]) {
int socket_info, new_socket;
struct sockaddr_in server, client;
char message[100];
char incoming_message[100];
printf("Input Message: ");
fgets(message, 100, stdin);
//create socket
socket_info = socket(AF_INET, SOCK_STREAM, 0);
if (socket_info == -1) {
printf("Could not create socket");
}
//assign values
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons( 1100 );
int y=1;
if(setsockopt(socket_info, SOL_SOCKET, SO_REUSEADDR, (char*)&y, sizeof(y)) == -1) {
perror("set reuseaddr");
return -1;
}
//binds socket
if (bind(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Bind error");
return 1;
}
//listen
listen(socket_info , 5);
//waiting for connection
puts("Waiting for incoming connections...");
int c = sizeof(struct sockaddr_in);
//accept connection
new_socket = accept(socket_info, (struct sockaddr *)&client, (socklen_t*)&c);
if (new_socket < 0){
perror("accept failed");
return 1;
}
puts("Connection accepted");
//send message
if( send(new_socket , message , strlen(message) , 0) < 0) {
perror("Send failed");
return 1;
}
puts("Message Sent");
//connects
if (connect(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Connected");
//Receive an incoming message
if( recv(socket_info, incoming_message , sizeof(incoming_message) , 0) < 0) {
perror("Received failed");
return 1;
}
puts("Message received");
incoming_message[strlen(incoming_message)-1]=0;
puts(incoming_message);
close(socket_info);
}
The second program is:
int main(int argc, char *argv[]) {
int socket_info, new_socket;
struct sockaddr_in server, client;
char incoming_message[100];
char message[100];
printf("Input Message: ");
fgets(message, 100, stdin);
//create socket
socket_info = socket(AF_INET, SOCK_STREAM, 0);
if (socket_info == -1) {
printf("Could not create socket");
}
//assign values
server.sin_addr.s_addr = inet_addr("172.21.8.178");
server.sin_family = AF_INET;
server.sin_port = htons( 1100 );
//connects
if (connect(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Connected");
//Receive an incoming message
if( recv(socket_info, incoming_message , sizeof(incoming_message) , 0) < 0) {
perror("Received failed");
return 1;
}
puts("Message received");
incoming_message[strlen(incoming_message)-1]=0;
puts(incoming_message);
int y=1;
if(setsockopt(socket_info, SOL_SOCKET, SO_REUSEADDR, (char*)&y, sizeof(y)) == -1) {
perror("set reuseaddr");
return -1;
}
//binds socket
if (bind(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Bind error");
return 1;
}
//listen
listen(socket_info , 5);
//waiting for connection
puts("Waiting for incoming connections...");
int c = sizeof(struct sockaddr_in);
//accept connection
new_socket = accept(socket_info, (struct sockaddr *)&client, (socklen_t*)&c);
if (new_socket < 0){
perror("accept failed");
return 1;
}
puts("Connection accepted");
//send message
if( send(new_socket , message , strlen(message) , 0) < 0) {
perror("Send failed");
return 1;
}
puts("Message Sent");
close(socket_info);
}
if (connect(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
Connection error: Transport endpoint is already connected
I asssume socket_info above should be new_socket?
You can't connect a listening socket.
You don't need to connect the listening socket. You have just accepted a socket from a client connection. You should do your I/O to that client with that socket.
In your second program:
if(setsockopt(socket_info, SOL_SOCKET, SO_REUSEADDR, (char*)&y, sizeof(y)) == -1) {
perror("set reuseaddr");
return -1;
}
This is futile. The socket is already bound, implicitly, via the connect() call preceding.
//binds socket
if (bind(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Bind error");
return 1;
}
Bind error: Cannot assign requested address
You can't bind a socket that is already connected.
Nor can you bind a socket to a remote address.
Nor can you listen on a connected socket.
Nor can you accept from it. You don't need to bind, or listen, or accept from it. You are already connected to the peer.
In short your code doesn't make any sense whatsoever. You need to find a proper tutorial and study it.
incoming_message[strlen(incoming_message)-1] = 0;
This makes even less sense. Here you are searching for a trailing null byte (which may not even be there) and replacing the byte before it by ... a null byte. Why?

Resources