Socket fails to bind (C with WinSock) - c

This is supposed to bind a socket to a port on the local host and accept TCP connections. When I run it, I get my "Bind error" message. I used this tutorial (see the "Accept connection" section), and the only significant difference I can see between that and my code is the position of the server address and port member initializations, which shouldn't matter, as long as they come before the bind() call?
I added a new rule in Windows Firewall (on Windows 7) to allow TCP connections from this executable, on port 8888, but that doesn't seem to help.
#include <stdio.h>
#include <winsock2.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;
printf("\nInitializing WinSock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error code: %d\n\n", WSAGetLastError());
exit(1);
}
printf("\nInitialized.");
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8888);
server.sin_family = AF_INET;
if (s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) == INVALID_SOCKET)
{
printf("\nCould not create socket: %d", WSAGetLastError());
exit(1);
}
printf("\nSocket created.\n");
if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("\nBind error.\n\n");
exit(1);
}
printf("\nSocket bound to port 8888.\n\n");
listen(s, 3);
printf("\nWaiting for incoming connections...");
c = sizeof(struct sockaddr_in);
new_socket = accept(s, (struct sockaddr *)&client, &c);
if (new_socket == INVALID_SOCKET)
{
printf("\nAccept failed.\n\n");
exit(1);
}
printf("\nConnection accepted.");
closesocket(s);
WSACleanup();
return 0;
}

This statement:
if (s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) == INVALID_SOCKET)
Needs an additional set of parenthesis around the assignment:
if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
The == operator has a higher precedence then the = operator (see Operator Precedence), so your original statement implicitly acts as if you had written it like this instead:
if (s = (socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) == INVALID_SOCKET))
If socket() succeeds, the comparison would evaluate to false, which then assigns 0 to s (since SOCKET is just an alias for UINT_PTR, assigning a boolean value to a SOCKET variable is allowed), and then bind() would fail with the WSAENOTSOCK error (if socket() fails, the comparison would evaluate to true, which would assign 1 to s, then the if would evaluate as true and your process would exit).
Personally, I dislike code that does assignments and comparisons in the same statement. This would be clearer and safer:
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET)
Also, don't forget to call closesocket() on new_socket after accept() succeeds.

Related

WinSock2 cant connect to simple server

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.

TCP client/server application using POSIX sockets: Server not receiving 2nd packet sent

I'm writing a 2D RPG game in pure ANSI C, and I've decided to implement multiplayer, so I've written boilerplate POSIX code for the client and server, and implemented a login packet. The login packet works fine, however with the addition of a logout packet when the client quits, the server never receives it.
I've stepped through in a debugger and when the write call is executed on the client socket the file descriptor is zero. I also set a memory watchpoint on the variable holding the client socket file descriptor, and it was never touched. I'm not sure whether this is a C bug, or something in networking I'm missing so I'm looking for a pointer of how to go about fixing it.
Creating client socket:
struct sockaddr_in sockaddr;
client = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client < 0) {
perror("");
exit(EXIT_FAILURE);
}
memset(&sockaddr, 0x00, sizeof(struct sockaddr_in));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(port);
inet_pton(AF_INET, server, &sockaddr.sin_addr);
if (connect(client, (struct sockaddr *)&sockaddr, sizeof(struct sockaddr)) < 0) {
perror("");
exit(EXIT_FAILURE);
}
Creating server socket:
struct sockaddr_in sockaddr;
server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server < 0) {
perror("");
exit(EXIT_FAILURE);
}
memset(&sockaddr, 0x00, sizeof(struct sockaddr_in));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(port);
sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(server, (struct sockaddr *)&sockaddr, sizeof(struct sockaddr_in)) < 0) {
perror("");
exit(EXIT_FAILURE);
}
int flags = fcntl(server, F_GETFL, 0);
flags &= ~O_NONBLOCK;
if (fcntl(server, F_SETFL, flags) < 0) {
perror("");
}
Listening on server socket:
if (listen(server, maxClients) < 0) {
perror("");
close(server);
exit(EXIT_FAILURE);
}
...
Main loop (threaded for future offline support):
void *mainLoop(void *argv) {
void (*packetHandler)(void) = argv;
for (;;) {
serverClient = accept(server, NULL, NULL);
printf("%d\n", serverClient);
if (serverClient < 0) {
exit(EXIT_FAILURE);
}
(*packetHandler)();
#ifdef SHUTDOWN
if (shutdown(serverClient, SHUT_RDWR) < 0) {
close(serverClient);
close(server);
exit(EXIT_FAILURE);
}
#endif
}
return NULL;
}
Writing to sockets is done using standard read and write calls.
Note: The #ifdef block with SHUTDOWN is normally not compiled.

Can reach my server with telnet but not with my client

I am currently coding a small chat application in C for learning network.
I develop using the Transmission Control Protocol with socket in C. I was able to connect to my server with a client not coded by myself (on local network). Now telnet succeed to connect to my chat server(so with server and telnet client on the same computer) and I can send and receive message BUT my very simple client cannot connect to it.
Since the begining I use port 9002 and right now I am trying to connect with IPv6 address ::1.
Here the "accept client" code of my server:
int main(void)
{
//Create the socket
int sock = socket(AF_INET6, SOCK_STREAM, 0);
printf("Socket créer\n");
//Set up the socket interface
struct sockaddr_in6 sin6 = { 0 };
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(PORT);
sin6.sin6_addr = in6addr_any;
//Bind the socket on the port
if(bind(sock, (struct sockaddr *) &sin6, sizeof(struct sockaddr_in6)) == SO_ERROR)
{
perror("bind()");
errx(EXIT_FAILURE, "Fail to bind");
}
//Make the sockey listen the port
if(listen(sock, MAX_CLIENT) == SO_ERROR)
{
perror("listen()");
errx(EXIT_FAILURE, "Fail to listen");
}
printf("Socket listening\n");
int csock;
size_t clientID = 0;
--snip--
while(1)
{
struct sockaddr_in6 csin6;
memset(&csin6, 0, sizeof(struct sockaddr_in6));
int sin6size = sizeof(struct sockaddr_in6);
//Accept a communication
printf("Wait for communication\n");
csock = accept(sock, (struct sockaddr *) &csin6, &sin6size);
printf("Connection accepted\n");
char msg[16];
sprintf(msg, "CONNECTED - %zu\n", clientID);
send(csock, msg, sizeof(msg), 0);
printf("Client %zu connected\n", clientID);
//Handle client
--snip--
}
So this is a basic connection with socket using connected communication. The server handle several client in the while loop thanks to threading.
Here the code of the client:
void *sender(void *arg)
{
int socket = (int)(long)arg;
char buffer[BUFF_SIZE];
while(1)
{
scanf("%s", buffer);
send(socket, buffer, strlen(buffer), 0);
bzero(buffer, BUFF_SIZE);
}
}
int main(int argc, char *argv[])
{
if(argc < 2)
errx(EXIT_FAILURE, "Usage: ./client <server ip>\n");
//Create the socket
int sock = socket(AF_INET6, SOCK_STREAM, 0);
struct hostent *hostinfo = NULL;
hostinfo = gethostbyname2(argv[1], AF_INET6);
if(hostinfo == NULL)
errx(EXIT_FAILURE, "Can't connect to the server\n");
//Set up the socket interface
struct sockaddr_in6 sin6 = { 0 };
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(PORT);
sin6.sin6_addr = *(struct in6_addr *)hostinfo->h_addr;
if(connect(sock, (struct sockaddr *) &sin6, sizeof(struct sockaddr)) == SO_ERROR)
{
perror("connect()");
errx(EXIT_FAILURE, "Fail to connect");
}
printf("Connection established\n");
pthread_t sending;
if(pthread_create(&sending, NULL, sender, (void *)(long)sock) != 0)
printf("Fail to create a thread\n");
//Handle reception
char buffer[BUFF_SIZE];
int n;
while((n = recv(sock, buffer, BUFF_SIZE - 1, 0)) >= 0)
{
buffer[n] = '\0';
printf("%s", buffer);
}
printf("Erreur: %d\nConnection broken\n", n);
pthread_cancel(sending);
close(sock);
return EXIT_SUCCESS;
}
So I start the client with:
~ ./client ::1
The output is the following:
Connection established
Error: -1
Connection broken
While the server is still "Waiting for communication". This means that the server do not accept the connection but the client succeed to connect.
Thank you for you help.
It is probably already the connect(), which fails here:
if(connect(sock, (struct sockaddr *) &sin6, sizeof(struct sockaddr)) == SO_ERROR)
SO_ERROR is not meant to be used here, but as a socket option when retrieving the error when an asynchronous connect fails. A (synchronous) connect() returns -1 on error and sets errno, so do
if(connect(sock, (struct sockaddr *) &sin6, sizeof(struct sockaddr)) == -1) {
...
Later, the recv here:
while((n = recv(sock, buffer, BUFF_SIZE - 1, 0)) >= 0)
fails with errno ENOTCONN, since the connection failed beforehand.
The same SO_ERROR mistake is present at various locations in your server code; it is possible, that already the bind() there fails! The call to listen() will then autobind it to a free ephemereal port, so the call as well as the call to accept() will succeed.
Why can the call to bind() fail? You might have to set the socket option SO_REUSEADDR when (re-)starting the server, otherwise it might refuse to use a recently bound port if connections are still in TIME_WAIT state. Place this directly before the bind() call:
int one = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
This might help.

Socket operation on non socket error in C

I am new to socket programming... I tried this server side program
#define BUFLEN 512
#define MYPORT 3456
void errorp(char* msg)
{
perror(msg);
exit(1);
}
int main()
{
struct sockaddr_in server, client;
int sock;
int slen = sizeof(server);
int clen = sizeof(client);
char *recvbuf, senbuf[BUFLEN] = {'h','e','l','l','o'};
if((sock = socket(AF_INET, SOCK_DGRAM, 0) == -1))
errorp("Socket creation failed");
printf("To the client: %s, %s", senbuf, " World");
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = MYPORT;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
if(bind(sock, (struct sockaddr*)&server, slen)==-1)
errorp("Socket Bind Failed");
if(recvfrom(sock, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*) &client, &clen) == -1)
errorp("recv from error");
printf("From the client: %s", recvbuf);
if(sendto(sock, senbuf, sizeof(senbuf), 0, (struct sockaddr*) &client, sizeof(client)) == -1)
errorp("Error in sending");
printf("To the client: %s", senbuf);
close(sock);
return 0;
}
There are no compilation errors but the output is
Socket Bind Failed: Socket operation on non-socket
To the client: hello, World
Please help me figure out where the mistake is?
and help get rid of it
The error message says it all: The socket isn't a (valid) socket.
This should make you look at the code creating the socket:
if((sock = socket(AF_INET, SOCK_DGRAM, 0) == -1))
The code above 1st compares the result of the call to socket() to -1 and then assigns the result of the comparison to sock. So it's either 0 or 1. And the result of the call to socket() is lost.
The code shall look like this:
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
as == binds tighter then =.
BTW, having used a Yoda-Conditition would have avoided such kind of "typo":
if (-1 == (sock = socket(AF_INET, SOCK_DGRAM, 0)))
Also at least clen shall be of type socklen_t as its address is passed, to have a value written into it, which will fail miserably if the size of the expected socklen_t would be different from an int (which the code shown passes).
if((sock = socket(AF_INET, SOCK_DGRAM, 0) == -1))
// \__________________________________/
You have your brackets in the wrong place. It's setting sock to a true/false value because == is "more binding" than =. It should instead be:
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
// \_____________________________________/
which sets sock to the return value from socket() and then compares that to -1.
You also have no backing storage for recvbuf which means your recvfrom(), once it starts working, will almost certainly do something bad.

Need multiple connections in C socket

I have written the following code as an intermediate to connect two programs. There is a server program running and a client program on two different systems. This code is expected to act as an intermediate between these two programs.
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
//Connect with program on server side
char * serv_con(char app_data[50])
{
int sock, bytes_recieved;
char send_data[1024];
char *recv_data = malloc(1024);
struct hostent *host;
struct sockaddr_in server_addr;
host = gethostbyname("10.47.3.249");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(3128);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),8);
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("Connect");
exit(1);
}
bytes_recieved=recv(sock,recv_data,1024,0);
recv_data[bytes_recieved] = '\0';
send(sock, app_data, 50, 0);
return recv_data;
//close(sock);
}
//Connect with client app
char * cli_con(char ser_data[50])
{
int sock, connected, bytes_recieved , true = 1;
char send_data [1024];
char *recv_data = malloc(1024);
struct sockaddr_in server_addr,client_addr;
int sin_size;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Socket");
exit(1);
}
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1)
{
perror("Setsockopt");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5000);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("Unable to bind1");
exit(1);
}
if (listen(sock, 5) == -1)
{
perror("Listen");
exit(1);
}
sin_size = sizeof(struct sockaddr_in);
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size1);
printf("\n I got a connection from (%s , %d)",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
bytes_recieved = recv(connected,recv_data,1024,0);
recv_data[bytes_recieved] = '\0';
send(connected, ser_data,50, 0);
//close(sock);
}
int main()
{
char *ser_data, *app_data;
int pid = fork();
while(1)
{
if(pid == 0)
app_data = serv_con(ser_data);
else
ser_data = cli_con(app_data);
}
}
It works fine until the client side app runs. But as soon as the client side app runs, the code exit giving the error:
Unable to bind: Address already in use
I got a connection from (192.168.0.3 , 45691)
What modification should I make in the code to rectify this error? I am working on linux. Thanks in advance.
EDIT:
I have removved the comment from close(sock)and added close(connect) in the function cli_con. The code on the client side is given below:
int sock, bytes_recieved;
char send_data[1024],recv_data[1024];
struct hostent *host;
struct sockaddr_in server_addr;
host = gethostbyname("192.168.0.2");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5555);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),8);
if (connect(sock, (struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1)
{
perror("Connect");
exit(1);
}
while(1)
{
//necessary codes
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
close(sock);
goto connct;
}
}
But now on running, the first program doesnot exit but doesnot even print
I got a connection from (192.168.0.3 , 45691)
But just keeps on running without printing ANY messages. But on the other hand, the client exits showing the error:
Connect: Connection reset by peer
What should I do now?
When a client disconnects you create a new server socket and bind it to the same port. If the server side socket was not closed the port is still in use, so bind fails.
Usually the server side of a socket program has a loop around accept to allow it process connections from many clients. This way bind and listen are called only once.
while (connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size1)) {
printf("\n I got a connection from (%s , %d)",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
bytes_recieved = recv(connected,recv_data,1024,0);
recv_data[bytes_recieved] = '\0';
send(connected, ser_data,50, 0);
close(connected);
}
It means you're trying to listen on port 5000, but there is already a program listening on that port (possibly an earlier version of your program which didn't close the port properly.) Change the port number to another value, or close any application listening on the port.
Since you're under Linux, you can use "netstat -nlp" as root to see what programs have which ports open.
One pointer for you is that, you should close both the listen socket and the socket which you obtain from the accept call.
close(connected);
close(sock);
Also, the socket takes sometime to be freed by the OS after it's usage and so, it might fail with an "Address already in use" error. You can check again properly in your code if your SO_REUSEADDR part of the code is executing properly.
Also, since you can try to add the listen socket creation code in your main function itself and pass it as an argument to cli_con function. Commonly followed mechanism is to create one listen socket and use it to accept multiple connections from client.
I hope in your original code you have proper memory allocation, initialization etc for ser_data & app_data.

Resources