Strange behaviour in a simple Client/Server Countdown C Application - c

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));

Related

Bool array transfer from server with UDP in C

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.

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){

C Programming multiple threads on XUbuntu

I'm trying make the program run multiple threads to it connects to different ports. I successfully made it work on a single thread but not multiple.
Below I have posted the code of what I'm using on XUbuntu.
server.c
#include <stdio.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
// File io storing in lof file
#include "server_portLog.h"
// Thread used to create sockets
#include "sockets_pthread.h"
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]) {
// Server port number
//int portNumber = atoi(argv[1]);
// sockfd: ip-address socket, newsockfd: socket from receiving client, portNum: Which port will be listening, num_bytes: received data from client
int sockfd, newsockfd, num_bytes;
// buffer: will send & receive values from the server
char buffer[BUFFER_SIZE];
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen = sizeof(cli_addr);
// Getting all ports from command line parameters and creating a socket for each
int numPorts = argc - 1;
struct port varPorts[numPorts];
pthread_t portsSockets[numPorts];
for (int i = 0; i < numPorts; i++) {
varPorts[i].portNumber = atoi(argv[i + 1]);
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&portsSockets[i], &attr, createSocket, &varPorts[i]);
}
// Infinite loop too keep listening even after connection to client closes
while (1) {
// After that all the ports entered have a socket of their own the program runs them parallel together to see if any client tries to connect with one of the ports
for (int i = 0; i <= numPorts; i++) {
pthread_join(&portsSockets[i], NULL);
/* Start listening for the clients (thread blocks) */
if (listen(varPorts[i].sockfd, 5) != 0) {
printf("Error: listen() failed for port: %d \n", varPorts[i].portNumber);
//return 3;
}
// Accepting connection from client & creating socket with that client data
newsockfd = accept(varPorts[i].sockfd, (struct sockaddr *)&cli_addr, &clilen);
if (newsockfd < 0) {
printf("Error: accept() failed for port: %d \n", varPorts[i].portNumber);
//return 4;
}
/* To send receive data */
// Clearing buffer
memset(buffer, 0, BUFFER_SIZE);
// Show data received from client
num_bytes = recv(newsockfd, buffer, BUFFER_SIZE-1, 0);
if (num_bytes < 0) {
printf("Error: recv() failed for port: %d \n", varPorts[i].portNumber);
//return 5;
}
// Checking version of server if LOGFILE it creates a file to store the ports
#if defined LOGFILE
// Checking if user wrote a fileName for the logs or going to use the default log file
if (argc == 3) {
char *textFile = argv[argc-1];
serverLogFile_Custom(buffer, textFile);
}
else {
serverLogFile_Defualt(buffer);
}
#else
// Print the port numbers that connect to server
printf("Received: Client using port- %s to connect \n", buffer);
#endif
// Closing connection with client
close(newsockfd);
}
}
return 0;
}
Sockets_pthreads.h
#include <pthread.h>
struct port {
int portNumber;
int sockfd;
};
void* createSocket(void* portNumber) {
// sockfd: ip-address socket, newsockfd: socket from receiving client, portNum: Which port will be listening, num_bytes: received data from client
int sockfd, newsockfd, num_bytes;
// buffer: will send & receive values from the server
//char buffer[BUFFER_SIZE];
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen = sizeof(cli_addr);
struct port *portStruct = (struct port*) portNumber;
// Creating a new socket with ip-Protocol_tcp
// Parameters: Internet-domain, socket-stream, TCP-protocol
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0) {
printf("Error: Failed to open socket for port: %d \n", portStruct->portNumber);
//return 1;
}
// Setting all bits in padding-field to 0
memset(&serv_addr, 0, sizeof(serv_addr));
// Initializing socket in sockaddr_in (stucture)
serv_addr.sin_family = AF_INET; // Seting family-Internet
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portStruct->portNumber); // Setting portNum (passed in command line)
// Binding the address-structure to the socket
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
printf("Error: bind() failed for port: %d \n", portStruct->portNumber);
//return 2;
}
// Geting sockfd
portStruct->sockfd = sockfd;
pthread_exit(0);
}
Problem is not clear what needs to be implemented. If various ports sockets have to accept, then it has to happen in thread function as well as recv call. In server function there are accept and recv calls which are blocking by default.
The main function should wait for connections. Upon receiving a request from the client, you create a thread that will handle this specific connection. So you will create the threads in the loop, meaning, you can theoretically have an infinite number of threads.
However, you can add a little logic to limit the number of threads that are existing at a particular time (thread pool).
So your main loop can look like this:
while (1) {
// accept: wait for a connection request
childfd = accept(parentfd, (struct sockaddr *) &clientaddr, (socklen_t *) &clientlen);
if (childfd < 0){
fprintf(stderr,"ERROR on accept");
continue;
}
hostaddrp = inet_ntoa(clientaddr.sin_addr);
if (hostaddrp == NULL){
fprintf(stderr,"ERROR on inet_ntoa\n");
continue;
}
fprintf(stdout,"server established connection with client\n");
pthread_t new_thread;
newSock = malloc(1);
*newSock = childfd;
if( pthread_create( &new_thread , NULL , server_thread , (void*) newSock) < 0){
bzero(logMsg, MAXSTRING);
sprintf(logMsg, "Thread for connection %d could not be created",childfd);
fprintf(stderr, "%s\n", logMsg);
continue;
}
fprintf(stdout, "thread created for connection %d\n", childfd);
}
The server_thread function could look like:
void *server_thread(void* clientSock){
int childfd = *(int*)clientSock;
char buf[MAXLINE]; // message buffer
int n; // message byte size
char logMsg[MAXSTRING];
size_t siz_failresp;
// read: read input string from the client
bzero(buf, MAXLINE);
n = (int) read(childfd, buf, MAXLINE);
if (n < 0){
sprintf(logMsg, "ERROR reading from socket");
fprintf(stderr,"%s", logMsg);
close(childfd);
fprintf(stdout, "Client %d disconnected \n=================\n", childfd);
//Free the socket pointer
free(clientSock);
return NULL;
}
// else, do processing of data received...
// ...................
}
There may be unused variables here above... I just got this code from one of my projects, just removing parts that do not concern you :-)
Hope it helps

Worker thread exits some time later

Here is a simple echo program using sockets and multi threads, it compiles and runs well in my Ubuntu if the client(via telnet) and server run on the same machine, but when I remotely connect to the server via telnet from another machine, it initially runs well(echos my message back every time), but some time later, there is no echo anymore even the telnet session is still alive, i am not sure where the problem is, can someone give some hits on this? I am new to multi thread programming and socket programming, learning on that.
#define ERROR -1
#define MAX_CLIENTS 2
#define MAX_DATA 1024
void* worker(void* sockId)
{
int socketId = *(int*)sockId;
int data_len = 1;
char data[MAX_DATA];
while(data_len > 0)
{
data_len = recv(socketId, data, MAX_DATA, 0);
if (data_len > 0)
{
send(socketId, data, data_len, 0);
data[data_len] = '\0';
printf("Sent message: %s", data);
}
}
printf("Client disconnected\n");
close(socketId);
}
int main(int argc, char* argv[])
{
if (argc <= 1)
{
printf("missing argument: port\n");
exit(-1);
}
struct sockaddr_in server;
struct sockaddr_in client;
int sock;
int new_connection;
int sockaddr_len = sizeof(struct sockaddr_in);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == ERROR)
{
perror("server socket: ");
exit(-1);
}
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1]));
server.sin_addr.s_addr = INADDR_ANY;
bzero(&server.sin_zero, 8);
if ((bind(sock, (struct sockaddr*)&server, sockaddr_len)) == ERROR)
{
perror("bind: ");
exit(-1);
}
if ((listen(sock, MAX_CLIENTS)) == ERROR)
{
perror("listen: ");
exit(-1);
}
while(1)
{
if ((new_connection = accept(sock, (struct sockaddr*)&client, &sockaddr_len)) == ERROR)
{
perror("accpet: ");
exit(-1);
}
printf("New Client connected from port: %d and IP: %s\n", ntohs(client.sin_port), inet_ntoa(client.sin_addr));
pthread_t thread;
pthread_create(&thread, NULL, worker, (void*)&new_connection);
pthread_detach(thread);
}
close(sock);
pthread_exit(NULL);
return 0;
}
Add some logging and you'll probably find that your code is blocked in send. You use naive, sequential I/O, so if the other end of the connection stops reading data, soon you do too.

Socket programming: recv/read issue

EDIT: the code below has been fixed to receive and send properly AND to account for the actual bytes of messages sent annd recieved (latter thanks to EJP)
I'm programming with C in Unix.
I have server and client that are supposed to exchange msgs. While client seems to send messages fine, server doesn't receive the messages the client is sending. I've tried using recv() and read() (i know they are practically the same thing but with extra flags on recv()) but I have no luck and I'm not really sure what the problem really is.
I put sleep(3) in the client code after every time it sends a message but i see that once client and server are connected, server immediately closes without waiting for the incoming messages. What am i doing wrong?
This is the client-side code:
#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE 500
int main(int argc, char * argv[])
{
int sockfd;
char * host;
char msg[MAX_DATA_SIZE];/* = "get my msg!\n";*/
int msg_len;
struct hostent * hp;
struct sockaddr_in client_address, server_address;
printf("y halo thar\n");
// looking up from the host database
if (argc == 2)
host = argv[1];
else
exit(1);
printf("sdf\n");
hp = gethostbyname(host);
if (!hp)
exit(1);
printf("host found\n");
// setting up address and port structure information
bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
server_address.sin_family = AF_INET;
bcopy(hp->h_addr, (char *) &server_address.sin_addr, hp->h_length);
server_address.sin_port = htons(SERVER_TCP_PORT);
printf("set\n");
// opening up socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
exit(1);
printf("opened\n");
// connecting
if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
exit(1);
printf("connected\n");
int i;
for (i = 0; i < MAX_DATA_SIZE; ++i)
{
msg[i] = '.';
}
msg[MAX_DATA_SIZE-1] = '\0';
for(i = 0; i < 11; i++)
{
// send message to connected socket
msg_len = write(sockfd, msg, MAX_DATA_SIZE);
if(msg_len < 1)
printf("notsent\n");
else
printf("%i bytes sent\n", msg_len);
// recieve messages from connected socket
msg_len = read(sockfd, msg, MAX_DATA_SIZE);
if (msg_len < 1)
printf("not recieved\n");
else
{
printf("%i bytes received\n", msg_len);
printf(msg);
printf("\n");
}
}
// close connection
close(sockfd);
printf("closed\n");
}
and this is the server side
#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE 500
int main()
{
printf("o halo thar\n");
int sockfd, new_sockfd;
int client_addr_len;
char msg [MAX_DATA_SIZE];
int msg_len;
char got_msg [11] = "got ur msg\0";
struct sockaddr_in server_address, client_address;
// setting up address and port structure information
bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(SERVER_TCP_PORT);
// opening up socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
exit(1);
printf("socket is opened\n");
// binding
if (bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
exit(1);
printf("socket is bound\n");
// listening
listen(sockfd,5);
printf("listening\n");
// block and wait for an incoming connection
client_addr_len = sizeof(client_address);
new_sockfd = accept(sockfd, (struct sockaddr *) &client_address, &client_addr_len);
if (new_sockfd < 0)
exit(1);
printf("accepted\n");
int i;
for( i = 0; i < 11; i++)
{
// recieve messages from connected socket
printf("waiting\n");
msg_len = read(new_sockfd, msg, MAX_DATA_SIZE);
if (msg_len < 1)
{
printf("no msg recieved\n");
}
else
{
printf("bytes recieved: %i\n", msg_len);
}
// send message to connected socket
msg_len = write(new_sockfd, got_msg, sizeof(got_msg));
if (msg_len < 1)
printf("not sent\n");
else
printf("%i bytes sent\n", msg_len);
}
// close connection
close(sockfd);
printf("socket closed. BYE! \n");
}
In the server code, the problem is on this line:
msg_len = read(sockfd, msg, MAX_DATA_SIZE);
You are calling read on sockfd, but you need to call read or recv on new_sockfd (the socket returned by accept()). new_sockfd is the one that's connected to the client (sockfd is used to accept further connections - eg if another client connects).
You should read from the socket returned by accept.
Try to call read on the socket returned from accept.
Receiver Side:
while(1)
{
len=read(sd,buff,sizeof(buff));
if(len==0)
{
//End of File receving.
break;
}
else
{
st=fwrite(buff,sizeof(char),len,fp);
}
}
Send Side:
while(!feof(fp))
{
len=fread(buff,sizeof(char),MW,fp);
if(len==0)
{
//EOF
st=write(cd,&d,sizeof(int));
break;
}
else
{
st=write(cd,buff,len);
}
}
is the implementation based on stream or datagram?
there are some problem with your operation flow. the server might start to read before client send anything.
since client and server are separated, you can imagine them running concurrently.
right after your server side "accept" connection request, there might be possibly some handshake overhead occurs or network delays causing server app to execute ahead in time, attempt to extract data but meet with errors (no data received yet).
you can try this out by adding sleep in server code after accept connection, where client should have enough time to send the data.
another better solution is to make data retrieval cope with empty buffer or asynchronous read.

Resources