Server client using select() - c

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.

Related

Transfer large packets in UDP

Hi thanks for reviewing my question, I am trying to transfer large packets using simple UDP sockets in C. OS is windows 10; IDE Visual Studio.
System build-up:
UDP client - Send 6250 packets of 8K.
UDP server - receive 8K packets count them, and print to the screen.
When I run the server and start to receive packets, I succeed to receive between 1500-2000 packets the rest are seen in WireShark but my program lost them.
I know that it can be that the sender side is writing much faster than the server reads but it looks like a large amount of packet loss.
How can I improve or change my server-side code to be able to stand the rate?
Server code:
SOCKET s;
struct sockaddr_in server, si_other;
int slen, recv_len;
uint8_t buf[BUFLEN] = {0} //8200B buffer;
WSADATA wsa;
slen = sizeof(si_other);
int countwrite = 0;
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");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
//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");
while (1)
{
printf("Waiting for data...");
fflush(stdout);
//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 ((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);
}
countwrite += 1;
printf("Packet Number : %d\n", countwrite);
}
Thank you for helping.

Bool array transfer from client with UDP in C

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.

Other PC can't connect to my server in C

I made a Server in C on port 100. The problem is that if anyone out of my PC writes telnet myip 100 he can't connect to my server!
Code:
#include <io.h>
#include <stdio.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include "ws2tcpip.h"
#pragma comment(lib,"ws2_32.lib")
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
struct sockaddr_in server, client;
int c;
char *message;
printf("\nInitialising Winsock...\n");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Winsock 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(100);
int inet_pton(int af, const char *src, void *dst);
//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 *)&client, &c)) != INVALID_SOCKET )
{
puts("Connection accepted");
//Reply to the client
message = "Hello Client, I have received your connection. But I have to go now... bye!\n";
send(new_socket, message, strlen(message) , 0);
}
if (new_socket == INVALID_SOCKET)
{
printf("Accept failed with error code: %d" , WSAGetLastError());
return 1;
}
closesocket(s);
WSACleanup();
return 0;
}
My provider is Fastweb (i'm from italy, i don't know if you know it).
What's the problem? The source code of the server or the provider?
Thank you a lot!

Multiple servers with single client

Scenerio: several servers are listening, and a single client will send a UDP broadcast to all machines on the network and the servers will reply back. (goal: get all the ip addresses of the servers)
Here is the client code:
int main()
{
struct sockaddr_in connectedSocket;
int length=sizeof(connectedSocket);
int iResult = 0, iOptVal = 0, nOptiontValue = 1;
SOCKET Socket;
char receiveBuffer[1000];
char message[1000];
//Clear the buffer by filling null, it might have previously received data
memset(receiveBuffer,'\0', 1000);
WSADATA wsa;
//Initialise winsock
printf("\nInitialising Winsock...\n");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("\nFailed. Error Code : %d",WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("\n.........Initialised.\n");
//Create socket
Socket = socket(AF_INET, SOCK_DGRAM, 0);
if (Socket == SOCKET_ERROR)
{
printf("Create a UDP socket failed with error = %d\n" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//Set socket options to broadcast
iResult = setsockopt(Socket, SOL_SOCKET, SO_BROADCAST,(char *) &iOptVal, sizeof (iOptVal));
if(iResult == SOCKET_ERROR)
{
printf("Set socket options failed with error = %d\n" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//Setup address structure
memset((char *) &connectedSocket, 0, sizeof(connectedSocket));
connectedSocket.sin_family = AF_INET;
connectedSocket.sin_port = htons(PORT);
connectedSocket.sin_addr.s_addr = INADDR_BROADCAST;
while(1)
{
printf("\n\n\nEnter message : ");
gets(message);
//send the message
if (sendto(Socket, message,sizeof(message) , 0 , (struct sockaddr *) &connectedSocket, sizeof(connectedSocket)) == SOCKET_ERROR)
{
printf("\nsendto() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("\nMessage Successfully sent to Server");
// fflush(stdout);
if (recvfrom(Socket, receiveBuffer, 1000, 0, (struct sockaddr *) &connectedSocket,&length) == SOCKET_ERROR)
{
printf("\nrecvfrom() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("\nServer Says : ");
printf(receiveBuffer,sizeof(receiveBuffer));
}
closesocket(Socket);
WSACleanup();
return 0;
}
When I run this, I get
sendto() failed with error code : 10013
I look up the winsock error and it says
An attempt was made to access a socket in a way forbidden by its access permissions. An example is using a broadcast address for sendto without broadcast permission being set using setsockopt(SO_BROADCAST).
But I am setting the sockopt to SO_BROADCAST. Can anyone tell me why this is happening?
The relevant parts of the code you posted are here:
int iResult = 0, iOptVal = 0, nOptiontValue = 1;
...
//Set socket options to broadcast
iResult = setsockopt(Socket, SOL_SOCKET, SO_BROADCAST,(char *) &iOptVal, sizeof (iOptVal));
if(iResult == SOCKET_ERROR)
{
printf("Set socket options failed with error = %d\n" , WSAGetLastError());
exit(EXIT_FAILURE);
}
Note that the variable iOptVal has been initialized 0. It's not modified anywhere else. Then you pass that variable to the setsockopt() function.
This sets the SO_BROADCAST option to FALSE. (Which is the default value, so actually it doesn't change the value).
It's not sufficient to set it. You have to set it to the correct value. Which would be TRUE.
You can do this by initializing the variable to 1 instead of 0.

Winsock send () over TCP in C

I'm just confusing using the send() function in Winsock. Does this code actually send a string "Hello" over TCP ?. I managed to establish a connection with a TCP client in LabVIEW but it seems like that this TCP server doesn't send anything.
#define DEFAULT_BUFLEN 1024
#include<stdio.h>
#include<winsock2.h>
#include<Ws2tcpip.h>
#include<stdlib.h>
#include<string.h>
#include<stdint.h>
#include<stddef.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET s , new_socket;
struct sockaddr_in server , client;
int c;
int iResult;
char *sendbuf = "Hello";
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( 13000 );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
}
puts("Bind done");
//Listen to incoming connections
listen(s , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
new_socket = accept(s , (struct sockaddr *)&client, &c);
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d" , WSAGetLastError());
}
iResult = send( new_socket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR)
{
wprintf(L"send failed with error: %d\n", WSAGetLastError());
closesocket(new_socket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %d\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(new_socket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
wprintf(L"shutdown failed with error: %d\n", WSAGetLastError());
closesocket(new_socket);
WSACleanup();
return 1;
}
}
Your code is not initialzing WinSock, not allocating any SOCKET object, and not establishing a connection between the socket and a peer before calling send(), so to answer your question:
NO, your code is NOT sending a string over TCP.
HOWEVER, if you fill in the missing pieces - call socket() to create a TCP socket, and call bind()/listen()/accept() to establish a TCP connection with a peer - then YES, your code will be sending the string over TCP.
You need to do something more like the following instead. This is just a simple example that establishes a single TCP connection and then exits once the string has been sent to the client. In a real-world application, you would need to leave the server socket open and continuously calling accept() if you want to service multiple client connections over time, even if just a single client ever connects, disconnects, and reconnects:
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET server_socket, client_socket;
struct sockaddr_in server_addr, client_addr;
int iResult;
char *sendbuf = "Hello";
iResult = WSAStartup(MAKEWORD(2, 0), &wsa);
if (iResult != 0)
{
wprintf(L"WinSock startup failed with error: %d\n", iResult);
return 1;
}
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == INVALID_SOCKET)
{
wprintf(L"socket failed with error: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
memset(&server_addr, 0, sizeof(server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(some port number here);
server_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(server_socket, (sockaddr*)&server_addr, sizeof(server_addr)) != 0)
{
wprintf(L"bind failed with error: %d\n", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}
if (listen(server_socket, 1) != 0)
{
wprintf(L"listen failed with error: %d\n", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}
iResult = sizeof(client_addr);
client_socket = accept(server_socket, (sockaddr*)&client_addr, &iResult);
if (client_socket == SOCKET_ERROR)
{
wprintf(L"accept failed with error: %d\n", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}
closesocket(server_socket);
iResult = send(client_socket, sendbuf, strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR)
{
wprintf(L"send failed with error: %d\n", WSAGetLastError());
closesocket(client_socket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %d\n", iResult);
closesocket(client_socket);
WSACleanup();
return 0;
}
Update: based on your updated code, try this:
#include <stdio.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stddef.h>
#pragma comment(lib, "ws2_32.lib") //Winsock Library
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET server_socket, client_socket;
struct sockaddr_in server_addr, client_addr;
int c, iResult;
char *sendbuf = "Hello";
printf("Initializing Winsock...\n");
iResult = WSAStartup(MAKEWORD(2,2), &wsa);
if (iResult != 0)
{
printf("WinSock initialization Failed. Error Code : %d", iResult);
return 1;
}
printf("WinSock Initialized.\n");
//Create a socket
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET)
{
printf("Could not create socket. Error Code : %d" , WSAGetLastError());
WSACleanup();
return 1;
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons( 13000 );
//Bind the listening port
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == SOCKET_ERROR)
{
printf("Bind failed. Error Code : %d", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}
printf("Socket bound to port 13000.\n");
//Listen to incoming connection
if (listen(server_socket, 1) == SOCKET_ERROR)
{
printf("Listen failed. Error Code : %d", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}
//Accept an incoming connection
printf("Waiting for incoming connection...\n");
c = sizeof(client_addr);
client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &c);
if (client_socket == INVALID_SOCKET)
{
printf("Accept failed. Error Code : %d", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}
printf("Client connected from %s:%hu\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
//Stop accepting incoming connections
closesocket(server_socket);
// Send string to client
iResult = send(client_socket, sendbuf, strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR)
{
printf("Send failed. Error Code : %d\n", WSAGetLastError());
iResult = 1;
}
else
{
printf("Bytes Sent: %d\n", iResult);
iResult = 0;
}
// shutdown the connection since no more data will be sent
if (shutdown(client_socket, SD_SEND) == SOCKET_ERROR)
{
printf("Shutdown failed. Error Code : %d\n", WSAGetLastError());
iResult = 1;
}
closesocket(client_socket);
WSACleanup();
return iResult;
}
No, it does not send the string "Hello". Even if the socket bind/accept/etc connection is OK, 'send(client_socket, sendbuf, strlen(sendbuf), 0);' does not send a C string. It sends five bytes, whereas the the C string "Hello" requires six bytes. Try:
send(client_socket, sendbuf, 1+strlen(sendbuf), 0);
A very high percentage of networking C code problems can be found by searching the source text for 'strlen'. printf(%s..), and assuming that TCP transfers messages longer than one byte, accounts for the rest:)

Resources