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.
Related
I'm learning networking on windows using C and I get this weird 10038 error
WSADATA wsa;
SOCKET connect_socket;
printf("Initialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}printf("Initialised.\n");
if (connect_socket = socket(AF_INET, SOCK_STREAM, 0) == INVALID_SOCKET) {
printf("Could not create socket : %d\n", WSAGetLastError());
return -1;
}
printf("Socket created.\n");
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(80);
server.sin_addr.s_addr = inet_addr("142.250.184.196");
if (connect(connect_socket, (struct sockaddr*)&server, sizeof(server)) != 0)
{
printf("connect error : %d\n", WSAGetLastError());
return 1;
}
printf("Connected\n");
return 0;
nslookup www.google.com -> "142.250.184.196"
when trying to run program prints: "
Initialising Winsock...Initialised.
Socket created.
connect error : 10038"
if (connect_socket = socket(AF_INET, SOCK_STREAM, 0) == INVALID_SOCKET) {
Based on the operator precedence in C this means
connect_socket = (socket(AF_INET, SOCK_STREAM, 0) == INVALID_SOCKET)
Thus connect_socket is not the actual socket but the result of the check if the socket is valid. Assuming that socket creation worked then connect_socket will thus be false, i.e. 0.
Since 0 is not a valid TCP socket connect will fail with error 10038:
WSAENOTSOCK
10038
Socket operation on nonsocket.
An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid.
To fix this, first assign to connect_socket, then compare with INVALID_SOCKET.
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.
I wanted to receive an *.xml data by port 3702.
So I made a example Server. And sended data by three port 1500,2500,3702.(Edit the PORT in line 43)
It worked and printed data correctly from port 1500,2500.
But when I set the PORT to 3702.
it returned me a error:**Bind failed with error code :10048**
I found that maybe it existed other Client IP were sending data by PORT 3702 in my LAN.
How can I fix it?
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define BUFLEN 8192 //Max length of buffer
#define PORT 3702 //The port on which to listen for incoming data
int main()
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen, recv_len;
char buf[BUFLEN];
WSADATA wsa;
slen = sizeof(si_other);
//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 a socket
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");
//keep listening for data
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);
}
//print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
printf("Data: %s\n", buf);
//now reply the client with the same data
}
closesocket(s);
WSACleanup();
return 0;
}
This is due to Address already in use.
Typically, only one usage of each socket address (protocol/IP address/port) is permitted. This error occurs if an application attempts to bind a socket to an IP address/port that has already been used for an existing socket, or a socket that was not closed properly, or one that is still in the process of closing. For server applications that need to bind multiple sockets to the same port number, consider using setsockopt (SO_REUSEADDR).
Client applications usually need not call bind at all - connect chooses an unused port automatically. When bind is called with a wildcard address (involving ADDR_ANY), a WSAEADDRINUSE error could be delayed until the specific address is committed. This could happen with a call to another function later, including connect, listen, WSAConnect, or WSAJoinLeaf.
typedef unsigned int uint16;
SOCKET s, new_socket;
uint16 port =18001;
void CreateSocket()
{
WSADATA wsa;
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");
//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);
//Binding between the socket and ip address
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);
//Accepting the incoming connection
new_socket = accept(s, NULL, NULL);
if (new_socket == INVALID_SOCKET)
{
printf(L"accept failed with error: %ld\n", WSAGetLastError());
closesocket(new_socket);
WSACleanup();
return 1;
}
else
printf("Client connected.\n");
closesocket(s);
}
int main()
{
CreateSocket();
return 0;
}
this is for TCP.
I am receiving a connection from the MASTER via the above ip address and port number, So I created a socket with port number and ip address for it. But how to check that the socket is active ?? how to check that the above socket code is valid (it's not showing any error). I am getting an error on the MASTER side saying that :
CONNECT EVENT CHECK FAILED (WSAGetLastError())
Could anyone help me in this ??
There is no connection between your socket and the address, you never bind() the address in server to the socket s.
Which, of course, is why your client fails to connect since the socket will not be using the expected port. I assume that you elsewhere call accept() and so on, to actually make the socket accept incoming connections, too.
I have to write a trceroute script but I'm not sure if my attempts are correct.
Right now I'm doing it like that (please correct me if I'm doing wrong or clumsy):
Got an struct for ip- and udpheader
A checksum function
Opening 2 sockets: One for sending UDP-packets in SOCK_RAW mode (to manipulate ttl) and one to receive ICMP-answers from the routers.
Using sendto() to send UDP packet
Having no clue how to receive and process an ICMP answer
Are there any more comfortable ways to change the TTL than using sock_raw where I have to define all header stuff by myself?
What parameters should I use for socket() when opening ICMP sock?
How to receive the ICMP answer?
What platform are you targeting? Here's a BSD flavor from OpenBSD source:
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
err(5, "icmp socket");
if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
err(5, "raw socket");
On Linux, I believe, you need to use IP_RECVERR and recvmsg(2) with the MSG_ERRQUEUE, see ip(7).
As far as setting the TTL is concerned, you can use setsockopt(). Here's an extract from the iputils' source for ping on Linux:
if (setsockopt(icmp_sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, 1) == -1) {
perror ("ping: can't set multicast time-to-live");
exit(2);
}
if (setsockopt(icmp_sock, IPPROTO_IP, IP_TTL, &ittl, sizeof(ittl)) == -1) {
perror ("ping: can't set unicast time-to-live");
exit(2);
}
I met the same problem and solved it.
You need to
create a new socket using ICMP protocol
bind to a specific port like 33434
receive ICMP reply.
I will show my code.
// ......create sending socket and fill the udp data...
// create socket to receive ICMP reply
SOCKET sock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,
WSA_FLAG_OVERLAPPED);
// from for receiving data about routing server
SOCKADDR_IN server_addr, from;
int fromlen = sizeof(from);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(33434);
// Set the receive and send timeout values to a second
timeout = 1000;
ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
sizeof(timeout));
if (ret == SOCKET_ERROR) {
printf("setsockopt(SO_RCVTIMEO) failed: %d\n", WSAGetLastError());
return -1;
}
timeout = 1000;
ret = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout,
sizeof(timeout));
if (ret == SOCKET_ERROR) {
printf("setsockopt(SO_SNDTIMEO) failed: %d\n", WSAGetLastError());
return -1;
}
// bind to the port 33434
int err = bind(sock, (SOCKADDR *)&server_addr, sizeof(SOCKADDR));
if (err != 0) {
fprintf(stderr, "bind with error: %d\n", WSAGetLastError());
return 3;
}
for (ttl = 1; ((ttl < maxhops) && (!done)); ttl++) {
int bwrote;
// Set the time to live option on the socket
set_ttl(sockRaw, ttl);
// Fill in some more data in the UDP header
((UdpHeader *)udp_data)->length = 8;
((UdpHeader *)udp_data)->dest_port = htons(33434);
((UdpHeader *)udp_data)->source_port = htons(33434);
((UdpHeader *)udp_data)->checksum =
checksum((USHORT *)udp_data, datasize);
// Send the UDP packet to the destination
bwrote = sendto(sockRaw, udp_data, datasize, 0, (SOCKADDR *)&dest,
sizeof(dest));
if (bwrote == SOCKET_ERROR) {
if (WSAGetLastError() == WSAETIMEDOUT) {
printf("%2d Send request timed out.\n", ttl);
continue;
}
printf("sendto() failed: %d\n", WSAGetLastError());
return -1;
}
// Read a packet back from the destination or a router along the way.
ret = recvfrom(sock, recvbuf, MAX_PACKET, 0, (struct sockaddr *)&from,
&fromlen);
if (ret == SOCKET_ERROR) {
if (WSAGetLastError() == WSAETIMEDOUT) {
printf("%2d Receive Request timed out.\n", ttl);
continue;
}
printf("recvfrom() failed: %d\n", WSAGetLastError());
return -1;
}
/* Decode the response to see if the ICMP response is from a router
* along the way or whether it has reached the destination. */
done = decode_resp(recvbuf, ret, &from, ttl);
Sleep(1000);
}
and it works on my computer. (Windows 10)
the result in my computer