I am trying to make an asynchronous UDP chat application, currently having only one client and server.
When I run my server, a lot of redundant data is displayed. Afterward, when some text is typed,
Error sending the file!
is displayed.
Could someone please look at the code and let me know where I am going wrong?
Server:
u_long iMode=1;
ioctlsocket(sd,FIONBIO,&iMode);
int n=sd+1;
fd_set readfds,writefds;
while(1)
{
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(sd,&readfds);
FD_SET(sd,&writefds);
int rv = select(n, &readfds, &writefds, NULL, NULL);
if(rv==-1)
{
printf("Error in Select!!!\n");
exit(0);
}
if(rv==0)
{
printf("Timeout occurred\n");
}
if (FD_ISSET(sd, &readfds))
{
FD_CLR(sd,&readfds);
int client_length = (int)sizeof(struct sockaddr_in);
memset(&buffer,0,sizeof(buffer));
int bytes_received = recvfrom(sd, buffer,SIZE, 0, (struct sockaddr *)&client, &client_length);
if (bytes_received < 0)
{
fprintf(stderr, "Could not receive datagram.\n");
closesocket(sd);
WSACleanup();
exit(0);
}
}
printf("\nClient says: %s",buffer);
printf("\nWrite :");
fgets(buffer,SIZE,stdin);
if(FD_ISSET(sd,&writefds))
{
FD_CLR(sd,&writefds);
int client_length = (int)sizeof(struct sockaddr_in);
if(sendto(sd, buffer,strlen(buffer), 0, (struct sockaddr *) &client,client_length)<0)
{
printf("Error sending the file! \n");
exit(1);
}
}
}
closesocket(sd);
WSACleanup();
return 0;
}
I see a problem. This line:
int rv = select(n, &readfds, &writefds, NULL, NULL);
Will nearly always return immediately with the readfds empty. But writefds will almost ALWAYS be set with the "sd" socket indicating that it is ready for writing/sending.
Hence, your code correctly skips the attempt to call recvfrom(), but nothing stops it from falling through to the sending code path. All of the variables such client, client_length, and buffer as are likely uninitialized at that point. Or worse, buffer and client are exactly what they were from the last successful call in the loop. That likely explains the redundant data.
My advice would be to not have a "writefds" set in the select call at all. Then only "send" when you actually read. The sendto call won't block for any significant amount of time anyway.
Related
I am developing a multi-client Unix Domain Socket to transfer data through multiple processes. I found some code that implements chat between every client and stuff but I want that once a client send something to the server, the server reply back and the client disconnect.
Having that said, I don't want while(fgets()) but I want (on client side):
int main() {
int sockfd;
struct sockaddr_un remote;
fd_set readfds;
char buf[1024];
char buf2[1024];
int len;
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
remote.sun_family = AF_UNIX;
strcpy(remote.sun_path, SOCK_PATH);
len = strlen(remote.sun_path) + sizeof(remote.sun_family);
if(connect(sockfd, (struct sockaddr*)&remote, len) == -1)
/* handle error */
FD_ZERO(&readfds);
FD_SET(0, &readfds);
FD_SET(sockfd, &readfds);
if(select(sockfd+1, &readfds, NULL, NULL, NULL) == -1)
/* handle error */
if(FD_ISSET(0, &readfds)) {
fgets(buf, 1024, stdin);
if(write(sockfd, buf, 1024) <= 0)
/* handle error */
}
if(FD_ISSET(sockfd, &readfds)) {
if(read(sockfd, &buf2, 1024) <= 0)
/* handle error */
}
printf("%s\n", buf2);
close(sockfd);
}
In this order, it works if I do everything after connect() twice (with a loop) but I want to do it only once. Without this loop, my server (which is a daemon) crash and I don't know why.
Furthermore, I added printf() from the code above to understand how it works:
(...)
printf("before select\n");
fflush(stdout);
if(select(sockfd+1, &readfds, NULL, NULL, NULL) == -1)
/* handle error */
printf("before select\n");
fflush(stdout);
if(FD_ISSET(0, &readfds)) {
fgets(buf, 1024, stdin);
if(write(sockfd, buf, 1024) <= 0)
/* handle error */
}
(...)
And I have this output:
before select
"input to fgets"
after select
And I don't understand why I have the input BEFORE "after select". It doesn't make any sense to me since I call fgets() after printf().
I hope this is understandable enough.
What's wrong with my code ? Did I miss something ?
The first time through, you call select() before the server has responded. The result is that sockfd won't be ready for reading.
In your case, the client might not need select() on the sockfd. You know that if you wrote something to the server you want to wait for the reply, right?
I'm trying to implement a simple multi-threaded client/server program: the client sends the server a number and the server creates a thread that sends back the number+1.
The problem is as follows:
The client connects to the server with no problems;
The thread is (as far as i can tell) created without issues; But after the client writes the number in the socket, the server simply doesn't see it. The call to read() gives no errors, it just sits there, waiting forever.
I tried sending more than one integer through it; no difference.
A suspicion i have is that the file descriptor server-side is passed incorectly to the thread,but i can't figure out how. Another suspicion i have is that i am missing something stupidly obvious.
Either way, help is appreciated.
Any ideas?
Server-side: the loop that creates threads.
while (1) {
int client;
printf("[server]Waiting at port %d...\n", PORT);
fflush(stdout);
int length = sizeof(from);
if (client = accept(sd, (struct sockaddr*)&from, &length) < 0) {
perror("[server]Error: accept().");
continue;
}
pthread_t th_id;
pthread_create(&th_id, NULL, &treat, &client);
}
Server-side: thread's treat function (the problem is here).
void* treat(void* client)
{
printf("[thread]Waiting for message...\n");
fflush(stdout);
pthread_detach(pthread_self());
int client_sd = *((int*)client);
int nr;
if (read(client_sd, &nr, sizeof(int))) {
perror("[thread]Error: read().");
exit(-1);
}
// The program won't reach this point.
printf("[thread]Read: %d", nr);
fflush(stdout);
close(*((int*)client));
return (NULL);
}
Client-side:
if (connect (sd, (struct sockaddr *) &server,sizeof (struct sockaddr)) == -1)
{
perror ("[client]Error: connect().\n");
return errno;
}
printf ("[client]Write a number: ");
fflush (stdout);
scanf("%d",&nr);
printf("[client] Read %d\n",nr);
if (write (sd,&nr,sizeof(int)) <= 0)
{
perror ("[client]Error: write()\n");
return errno;
}
//the program reaches here.
printf("[client]The message was sent\n");
The problem is at line
if (client = accept(sd, (struct sockaddr*)&from, &length) < 0) {
it is interpreted as
if (client = (accept(sd, (struct sockaddr*)&from, &length) < 0)) {
and if accept returns positive then the client is set to 0. Subsequent read in the thread is read from stdin then.
I am writing a C software to interface with a motorcontroller over UDP.
I'm using:
Win 7 Pro 64-Bit
eclipse luna
minGW
At the moment I have a problem, that seems to be socket/wsa related:
the execution of my program gets stuck on the recvfrom() forever (so obviously the controller doesn't respond as expected).
With the attached software this only happens on the first execution (or after not executing for ca. 3 mins) other programs had this problem 3-4 times in a row.
A look into wireshark revealed, that the first (or after 3min pause) leads to the transmission of an "ARP" package instead of my UDP message.
Why is that (it seems to be searching for the destination)? How can I avoid "crashing" my software due to this?
Did I forget to initialise anything?
My code looks like this:
#include <stdio.h>
#include <conio.h>
#include <winsock2.h>
#define Y_AXIS_IP "XXX.XXX.XXX.XX"
#define Y_AXIS_PORT 880X
int startWinsock(void);
int main() {
//Start the winsocket (needed to create sockets)
long ws = startWinsock();
if (ws) {
printf("ERROR: Failed to init Winsock API! Code: %ld\n", ws);
getch();
exit(EXIT_FAILURE);
}
//Create an UDP Socket
SOCKET UDPsocket = socket(AF_INET, SOCK_DGRAM, 0);
if (UDPsocket == INVALID_SOCKET) {
printf("ERROR: Socket could not be created! Code: %d\n",
WSAGetLastError());
getch();
exit(EXIT_FAILURE);
}
//Create a struct to use with the socket (this gives information about type (AF_INET = Internet Protocol) which port and which IP to use)
SOCKADDR_IN addrY;
memset(&addrY, 0, sizeof(addrY));
addrY.sin_family = AF_INET; //Assert Type
addrY.sin_port = htons(Y_AXIS_PORT); //Assert Port
addrY.sin_addr.S_un.S_addr = inet_addr(Y_AXIS_IP); //assert IP Address
char message[] = "0000MTX 00000000OR:1:000F\r";
int buffersize = 100;
char *recvbuf = malloc(buffersize); //None of the replys can get larger than 100 chars
if (recvbuf == NULL) {
printf("Out of memory!\n");
getch();
exit(EXIT_FAILURE);
}
//clear the receive buffer and prepare the address size
memset(recvbuf, '\0', buffersize);
int addrsize = sizeof(addrY);
//Send the message to the device
if (sendto(UDPsocket, message, strlen(message), 0,
(struct sockaddr *) &addrY, sizeof(addrY)) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d", WSAGetLastError());
getch();
exit(EXIT_FAILURE);
}
//Receive from device (blocks program until recv event)
if (recvfrom(UDPsocket, recvbuf, buffersize, 0, (struct sockaddr *) &addrY,
&addrsize) == SOCKET_ERROR) {
//If not timed out Display the Error
printf("recvfrom() failed with error code : %d", WSAGetLastError());
getch();
exit(EXIT_FAILURE);
}
printf("%s\n", recvbuf);
getch();
free(recvbuf);
return 0;
}
int startWinsock(void) {
WSADATA wsa;
return WSAStartup(MAKEWORD(2, 2), &wsa);
}
I would be really happy, if you had any ideas or suggestions. Thanks alot in advance!
Before a computer can send a packet to another host, it has to resolve its MAC address. This is done via an ARP request. It is handled by the operating system transparently.
recvfrom will block. It is not a bug. There are basically three ways of avoiding recvfrom from blocking forever when there is no incomming data:
make the socket asynchronous, i.e. nonblocking
set a timeout (see Set timeout for winsock recvfrom)
use select (Setting winsock select timeout accurately)
So finally I found a way to deal with this issue:
1. catch the timeout that occurs at recvfrom
2. save the sockets address in a temporary socket
3. close the original socket
4. end the WSA (call WSACleanup())
5. start the WSA (call WSAStartup())
6. create a new socket at the address of the former socket
7. transmit the message again
seems to work fine (also see code below)
If you see anything wrong or dangerous with my code, please feel free to comment and help my to improve my skills.
Thank you for your help and ideas,
Sebastian
Code:
if (recvfrom(*UDPsocket, buffer, buffersize, 0, (struct sockaddr *) &addr,
&addrsize) == SOCKET_ERROR) {
int WSAerror = WSAGetLastError();
if (WSAerror == 10060) {
printf("[WARNING] recvfrom() timed out!\n");
//Store the address of the socket
SOCKET *tempsocket = NULL;
tempsocket = UDPsocket;
//destroy the old socket
closesocket(*UDPsocket);
WSACleanup();
//create a new socket
startWinsock();
*tempsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//Send the message to the device
if (sendto(*tempsocket, Frame.pcompletemsg,
strlen(Frame.pcompletemsg), 0, (struct sockaddr *) &addr,
sizeof(addr)) == SOCKET_ERROR) {
printf("[ERROR] sendto() failed with error code : %d\n",
WSAGetLastError());
getch();
WSACleanup();
exit(EXIT_FAILURE);
}
if (recvfrom(*tempsocket, buffer, buffersize, 0,
(struct sockaddr *) &addr, &addrsize) == SOCKET_ERROR) {
int WSAerror = WSAGetLastError();
printf("[ERROR] recvfrom() failed with error code : %d",
WSAerror);
getch();
WSACleanup();
exit(EXIT_FAILURE);
}
} else {
printf("[ERROR] recvfrom() failed with error code : %d", WSAerror);
getch();
WSACleanup();
exit(EXIT_FAILURE);
}
}
Currently I am working on a single server,single client udp chat application. Initially I used blocking sockets which is the default condition. Now I want to convert the socket into non-blocking so that communication between client and server could be done without the obstacle of turns...
I've implemented the select function on the server side for now,but the when it starts the client gets to send a message once which is displayed on the server side,afterwards both client and server get unresponsive, so now I am showing how have I implemented the select() function on the server side:
//Declaring a non-blocking structure
fd_set readfds,writefds;
// clear the set ahead of time
FD_ZERO(&readfds);
FD_ZERO(&writefds);
// add our descriptor to the set
FD_SET(sd, &readfds);
FD_SET(sd, &writefds);
/value of sd+1
int n=sd+1;
Since I want to both receive and send data,I've implemented the select function in the loop:
int client_length = (int)sizeof(struct sockaddr_in);
int rv = select(n, &readfds, NULL, NULL, NULL);
if(rv==-1)
{
printf("Error in Select!!!\n");
exit(0);
}
else if(rv==0)
{
printf("Timeout occurred\n");
}
else
if (FD_ISSET(sd, &readfds))
{
int bytes_received = recvfrom(sd, buffer,SIZE, 0, (struct sockaddr *)&client, &client_length);
if (bytes_received < 0)
{
fprintf(stderr, "Could not receive datagram.\n");
closesocket(sd);
WSACleanup();
exit(0);
}
}
further for sending data:
fgets(buffer,SIZE,stdin);
int rv1 = select(n, &writefds, NULL, NULL, NULL);
if(rv1==-1)
{
printf("Error in Select!!!\n");
exit(0);
}
else if(rv1==0)
{
printf("Timeout occurred\n");
}
else
if(FD_ISSET(sd,&writefds))
{
if(sendto(sd, buffer,strlen(buffer), 0, (struct sockaddr *) &client,client_length)<0)
{
printf("Error sending the file! \n");
exit(1);
}
}
}
So I would really appreciate if somoone let me know whether I've done this right or not,if this is ok then will the same implelementation on the client side resolve my issue?
This is incorrect:
select(n, &writefds, NULL, NULL, NULL);
The second argument is used to check for readability only. To check for writability, use the third argument:
select(n, NULL, &writefds, NULL, NULL);
I'm trying to figure out what is blocking my program. I'm running a server that uses POSIX threads. I have to for my computer programming lab. The main function listens for new connections. Once it accepts a connection, it creates a new thread by passing the FD to the thread. I'm able to successfully connect to the server using multiple telnet/client connections. I can send data to the server successfully once, but if I try sending again the server won't do anything.
Part of the main function
int active_thread = 0;
//The Running loop
while(running)
{
if(active_thread > NUMBTHREADS)
{
printf("Unable to accept client connection! Threads are all used up");
running = false;
}
else
{
if(FD_ISSET(sockfd, &readfds))
{
if((bindfd[active_thread] = accept(sockfd, (struct sockaddr *) &client_addr, &client_sock_size)) == -1)
{
fprintf(stderr, "Unable to accept client \n");
perror("What");
break;
}
activethreads[active_thread] = pthread_create( &threads[active_thread], NULL, server_handler, (void*) &bindfd[active_thread]);
//close(bindfd[active_thread]);
//pthread_join( threads[active_thread], NULL);
active_thread++;
//running = false;
}
}
}
close(sockfd);
return 0;
}
Part of the POSIX THREAD CODE
void *server_handler( void *sockfd)
{
int bindfd = *( (int *) sockfd);
char buffer[MESSAGELENGTH];
bool running = true;
printf("Thread was created successfully\n");
char intro[] = "Successfully Connected to server!\n";
struct pollfd pfd;
pfd.fd = bindfd;
pfd.events = POLLIN;
if ( (send(bindfd, intro, strlen(intro), 0)) < 0)
{
perror("Unable to send");
}
while(running){
char msg[] = "\nYou have the following options!\n1) Insert an integer: insert <integer>\n2) Remove An Integer: remove <integer>\n3) Get number of integers in list: get_count\n4) Get first integer: get_first\n5) Get last integer: get_last\n6) Quit program: quit\n ";
if ( (send(bindfd, msg, strlen(msg), 0)) < 0)
{
perror("Unable to send");
}
memset(&buffer, 0, MESSAGELENGTH);
if (recv(bindfd, buffer, MESSAGELENGTH, 0) > 0)
{
//SOme other code
}
}
I think its blocking at either the accept or recv. I've heard of select() and various other methods, but I'm having difficulty trying to implement them. Thanks!
The root cause of your issue appears to be that you are unconditionally executing close(sockfd); return 0; at the bottom of your while (running) loop, which means that the loop only ever executes once.
Additionally, you should not be using FD_ISSET() unless you are also using select(). Your main loop should look something more like:
int active_thread = 0;
while (active_thread < NUMBTHREADS)
{
if((bindfd[active_thread] = accept(sockfd, (struct sockaddr *) &client_addr, &client_sock_size)) == -1)
{
fprintf(stderr, "Unable to accept client \n");
perror("What");
break;
}
activethreads[active_thread] = pthread_create( &threads[active_thread], NULL, server_handler, (void*) &bindfd[active_thread]);
active_thread++;
}
if (active_thread >= NUMBTHREADS)
{
printf("Unable to accept client connection! Threads are all used up.\n");
}
running = false;
close(sockfd);
return 0;
By default network sockets are blocking. You need to set the O_NONBLOCK flag on the socket.
if(fcntl(fd, F_GETFL, &flags) < 0 ||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)
perror("Failed to set socket as non-blocking");
Now, instead of blocking when there is no input (or buffer space to store output), the error EAGAIN (or EWOUDLBLOCK) is returned. Lastly, you will need to use select() or poll() when you have nothing else to do but wait on I/O. These calls will only wake the process when either there is input, room for output, or possibly a time-out period passes.
int maxFd;
fdset fds;
FD_ZERO(&fds);
FD_SET(listenFd, &fds);
FD_SET(sockFd1, &fds);
FD_SET(sockFd2, &fds);
maxFd = listenFd+1;
maxFd = sockFd1 > maxFd ? sockFd1+1 : maxFd;
maxFd = sockFd2 > maxFd ? sockFd2+1 : maxFd;
if(select(maxFd, &fds, &fds, &fds, NULL) < 0) {
perror("Failed on select()");
exit(1);
}
if(FD_ISSET(listenFd, &fds))
...
This example is not complete or neccessarily 100% correct, but should be a good start. Also, I tend to reserve using send*() and recv*() when dealing with SOCK_DGRAM sockets and just use read(), write() on SOCK_STREAM sockets.