The following code opens a UDP socket and binds to a privileged port which fails. I want to retrieve the error through getsockopt (SO_ERROR) but I can't. The errno var is 13 but from getsockopt I get 0. I was under the impression getsockopt was the preferred method?
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/time.h>
#include <errno.h>
int main() {
int _fd = socket (AF_INET, SOCK_DGRAM,
IPPROTO_UDP);
int on = 1;
int rc = setsockopt (_fd, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<char *> (&on), sizeof (on));
assert(rc == 0);
struct sockaddr_in server;
memset(&server, 0, sizeof server);
server.sin_family = AF_INET; // Use IPv4
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(151); // Bind port
rc = rc | bind (_fd, (struct sockaddr *)&server, sizeof(server));
int err = -1;
socklen_t len = sizeof err;
int rc2 = getsockopt (_fd, SOL_SOCKET, SO_ERROR, &err, &len);
printf("end rc=%i rc2=%i err=%i errno=%i : %m\n", rc, rc2, err, errno);
sleep(10);
}
I think you misunderstand what SO_ERROR is for. It's not a substitute for errno - that has already told you why the call to bind failed.
Instead, it is meant to be used for established connections that might encounter an error condition which cannot be reported immediately (such as an asychronous operation on a non-blocking socket). There's a better description than the rather bare-bones man page here:
https://www.ibm.com/docs/en/zvse/6.2?topic=SSB27H_6.2.0/fa2ti_call_getsockopt.htm
Related
I learn how application works themself by Internet. I wrote a client program which sends a message to a server program, then that message should be printed in a server program, but this message prints into a client program. Here code server program and client program, also header file to redefine some types.
There are not any errors and warning while compiling, so I didn't send a compiling process.
server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/un.h>
#include "../main_values.h"
int main()
{
int socket_server = socket(AF_INET, SOCK_STREAM, 0); //create a socket server
int opt = 1;
setsockopt(socket_server, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); //set an option to socket to
//if we ends working with
sockaddr_in addr_server; //socket connected with
addr_server.sin_family = AF_INET; //ip address, free ip
addr_server.sin_port = htons(2251);
addr_server.sin_addr.s_addr = inet_addr("127.0.0.222");
int stat = bind(socket_server, (sockaddr *)&addr_server, sizeof(addr_server)); //connecting ip addr and socket
if (stat == -1)
{
perror("ERROR");
}
sockaddr_in addr_client; //create the future client ip stucture
socklen_t len = 0;
listen(socket_server, 15); //set server socket into listening
int socket_client = accept(socket_server, (sockaddr *)&addr_client, &len); //connecting client ip with our socket
if (socket_client == -1)
{
perror("ERROR");
}
char msg[100];
int res = read(socket_server, msg, sizeof(msg)); //getting message from client
printf("MESSAGE FROM CLIENT: %s\n", msg); //printing message from client
shutdown(socket_server, SHUT_RDWR); //closing server socket
return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/un.h>
#include "../main_values.h"
int main()
{
int socket_client = socket(AF_INET, SOCK_STREAM, 0); //create a client socket
int opt = 1; //set an option like in a server.c
setsockopt(socket_client, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
sockaddr_in addr_client; //making client ip structure
addr_client.sin_family = AF_INET;
addr_client.sin_port = htons(2250);
addr_client.sin_addr.s_addr = htons(INADDR_ANY);
int stat = bind(socket_client, (sockaddr *)&addr_client, sizeof(addr_client)); //connecting ip and client socket
if (stat == -1)
{
perror("ERROR");
}
sockaddr_in addr_server; //creating a server ip structure
addr_server.sin_family = AF_INET;
addr_server.sin_port = htons(2251);
addr_server.sin_addr.s_addr = inet_addr("127.0.0.222");
int socket_server = connect(socket_client, (sockaddr *)&addr_server, sizeof(addr_server));
if (socket_server == -1) //connecting to server
{
perror("ERROR");
}
char msg[] = "HELLO WORLD!!!!!"; //excample message
int res = write(socket_server, msg, sizeof(msg)); //sending a message to server
shutdown(socket_client, SHUT_RDWR);
return 0;
}
main_values.h
#pragma once
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
terminal_1
ch#ch:~/Рабочий стол/mainc.4/my_server$ ./server.out
MESSAGE FROM CLIENT:
ch#ch:~/Рабочий стол/mainc.4/my_server$
terminal_2
ch#ch:~/Рабочий стол/mainc.4/my_server$ ./client.out
HELLO WORLD!!!!!ch#ch:~/Рабочий стол/mainc.4/my_server$
int socket_server = connect(socket_client, (sockaddr *)&addr_server,
...
int res = write(socket_server, msg, sizeof(msg));
The return code of connect is 0 if the connect succeeded. Thus socket_server is 0. This means a write to file descriptor 0 is done, which is the equivalent to stdin and thus results into a write to the terminal.
The correct code would be to write to socket_client, not socket_server. The naming suggests that there is some confusion of what connect returns, i.e. it returns a status and not a new socket. Please see the documentation for connect for details.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char *argv[]){
// established the socket
char inputBuffer[256] = {};
char message[] = {"Hi this is the server.\n"};
int sockfd = 0;
int forClientSocketfd = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1) printf("Fail to create the socket.");
// socket connection
struct sockaddr_in serverInfo, clientInfo;
int addrlen = sizeof(clientInfo);
bzero(&serverInfo, sizeof(serverInfo));
serverInfo.sin_family = PF_INET;
serverInfo.sin_addr.s_addr = INADDR_ANY;
serverInfo.sin_port = htron(10024);
bind(sockfd, (struct sockaddr *) &serverInfo, sizeof(serverInfo));
listen(sockfd, 5);
while(1){
forClientSocketfd = accept(sockfd, (struct sockaddr*) &clientInfo, &addrlen);
send(forClientSocketfd, message, sizeof(message), 0);
recv(forClientSocketfd, inputBuffer, sizeof(inputBuffer), 0);
printf("Received from client: %s\n", inputBuffer);
}
return 0;
}
This is the code for socket programming that I seen through from the net. when I compiled it, it throw the error message as below. Having no idea what's going on, even though searching through the internet. p.s. Client operate as normal.
enter image description here
you have a typo on line number 24 it should be htons and not htron
htons()
The htons function takes a 16-bit number in host byte order and returns a 16-bit number in network byte order used in TCP/IP networks(the AF_INET or AF_INET6 address family). The htons function can be used to convert an IP port number in host byte order to the IP port number in network byte order
also add the stdio header file to your code to remove the other warnings
heres the final corrected code with no warnings or errors.
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
// established the socket
char inputBuffer[256] = {};
char message[] = {"Hi this is the server.\n"};
int sockfd = 0;
int forClientSocketfd = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
printf("Fail to create the socket.");
// socket connection
struct sockaddr_in serverInfo, clientInfo;
int addrlen = sizeof(clientInfo);
bzero(&serverInfo, sizeof(serverInfo));
serverInfo.sin_family = PF_INET;
serverInfo.sin_addr.s_addr = INADDR_ANY;
serverInfo.sin_port = htons(10024);
bind(sockfd, (struct sockaddr *)&serverInfo, sizeof(serverInfo));
listen(sockfd, 5);
while (1)
{
forClientSocketfd = accept(sockfd, (struct sockaddr *)&clientInfo, &addrlen);
send(forClientSocketfd, message, sizeof(message), 0);
recv(forClientSocketfd, inputBuffer, sizeof(inputBuffer), 0);
printf("Received from client: %s\n", inputBuffer);
}
return 0;
}
I made a TCP Client/Server and I can run it one time. But when I try to run it more than one time, it gives me the following error: "Connection refused". Here's my code.
Client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int net_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in net_addr;
net_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
net_addr.sin_family = AF_INET;
net_addr.sin_port = htons(3250);
int connection_state = connect(net_socket, (struct sockaddr*)&net_addr, sizeof(net_addr));
if (connection_state == 0) {
printf("Connected with the server.\n");
}
else {
printf("Connection with the server failed. [%s]\n", strerror(errno));
}
char net_message[256];
recv(net_socket, net_message, sizeof(net_message), 0);
close(net_socket);
shutdown(net_socket, SHUT_RDWR);
return 0;
}
Server
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int net_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in net_addr;
net_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
net_addr.sin_family = AF_INET;
net_addr.sin_port = htons(3250);
bind(net_socket, (struct sockaddr*)&net_addr, sizeof(net_addr));
listen(net_socket, 1);
struct sockaddr_in cl_addr;
int cl_size = sizeof(cl_addr);
int cl_socket = accept(net_socket, (struct sockaddr*)&cl_addr, (socklen_t*)&cl_size);
int loop = 1;
char net_message[256];
send(cl_socket, net_message, sizeof(net_message), 0);
close(net_socket);
close(cl_socket);
shutdown(net_socket, SHUT_RDWR);
shutdown(cl_socket, SHUT_RDWR);
return 0;
}
I've been trying to solve the problem by many ways but I'm a newbie. Thanks for the help in advance!
The problem is with your server lacking the SO_REUSEADDR socket option which leads to the bind() syscall failing. The reason is, that after a client disconnects from the server, the connection is still known by the system in TIME_WAIT state, to wait for late packets. These lead to the bind() to fail with EADDRINUSE if the above mentioned socket option is not set.
Use the following:
...
int one = 1;
setsockopt(net_socket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
bind(net_socket, (struct sockaddr*)&net_addr, sizeof(net_addr));
...
and do error checks for all syscalls! That would have shown you the problem much earlier and had saved you much time.
Some more issues:
You are sending an uninitialized buffer net_message
A shutdown on a listen socket isn't sensible at all, since no connection is established on it (this here: shutdown(net_socket, SHUT_RDWR);)
The shutdown on the client socket has - if at all - to be performed before the close(cl_socket);. But it is not necessary at all in that case.
My code will always proc the "Binding Failure" error and I do not know why. I have read the man page multiple times and I can't find anything wrong with the code, can someone please steer me in the right direction?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 3490
#define BACKLOG 10
int main()
{
struct sockaddr_in server;
struct sockaddr_in dest;
int status,socket_fd, client_fd,num;
socklen_t size;
char buffer[10241];
char *buff;
// memset(buffer,0,sizeof(buffer));
int yes =1;
if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== -1) {
fprintf(stderr, "Socket failure!!\n");
exit(1);
}
if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
memset(&server, 0, sizeof(server));
memset(&dest,0,sizeof(dest));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = INADDR_ANY;
if ((bind(socket_fd, (struct sockaddr *)&server, sizeof(struct sockaddr )))== -1) { //sizeof(struct sockaddr)
fprintf(stderr, "Binding Failure\n");
exit(1);
//other irrelevant code starts here
If netstat -an|grep 3490 really shows 127.0.0.1 you have another process listening at the port, bound to 127.0.0.1 instead of INADDR_ANY, which is why the SO_REUSEADDR didn't work. But you will never know for sure until you take my advice above.
After using perror, I found that the address was taken and I switched to another port and it worked!
I am performing communication between client(windows) and server(linux RT) in c. I have written a client code for windows operating system (one laptop) and server code for linux operating system (another laptop). I am connecting the both laptop via ethernet cable and configured them on the same subnet.
SERVER.c : Linux
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define BUFLEN 512
#define PORT 9930
void err(char *str)
{
perror(str);
exit(1);
}
int main(void)
{
struct sockaddr_in my_addr, cli_addr;
int sockfd, i;
socklen_t slen=sizeof(cli_addr);
char buf[BUFLEN];
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
err("socket");
else
printf("Server : Socket() successful\n");
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr* ) &my_addr, sizeof(my_addr))==-1)
err("bind");
else
printf("Server : bind() successful\n");
while(1)
{
if (recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr,
&slen)==-1)
err("recvfrom()");
printf("Received packet from %s:%d\nData: %s\n\n",
inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), buf);
}
close(sockfd);
return 0;
}
CLIENT.c - windows
#pragma comment(lib, "Ws2_32.lib")
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <winsock.h>
#include <io.h>
#define BUFLEN 512
#define PORT 9930
void err(char *str)
{
perror(str);
exit(1);
}
int main(void)
{
struct sockaddr_in my_addr, cli_addr;
int sockfd, i;
socklen_t slen=sizeof(cli_addr);
char buf[BUFLEN];
WORD wVersionRequested;
WSADATA wsaData;
printf("Initializing Winsock\n");
wVersionRequested = MAKEWORD (1, 1);
if (WSAStartup (wVersionRequested, &wsaData) != 0){
printf("Winsock initialised failed \n");
} else {
printf("Initialised\n");
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
err("socket");
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if (inet_aton(argv[1], &serv_addr.sin_addr)==0)
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
while(1)
{
printf("\nEnter data to send(Type exit and press enter to exit) : ");
scanf("%[^\n]",buf);
getchar();
if(strcmp(buf,"exit") == 0)
exit(0);
if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, slen)==-1)
err("sendto()");
}
close(sockfd);
return 0;
}
My question :
Is it possible to perform communication like this ??
Do I want to take specific measures for doing this ??
Please give ideas regarding this ?
You can connect two systems directly (via ethernet cable), but typically you must use a special cable for that: it is called a "crossover cable". Otherwise no connection is possible.
Newer network controllers implement a detection for this kind of setup, so it might be possible to use a standard cable for this setup, but this depends on the network controllers build into the two systems. You will have to try or consult the documentation.
Also it migh be that you have to select some special configuration on the MS-Windows side (inside the network adapter configuration) for this to work. I experienced communication problems with the standard setup a few times. You can consult google for those settings.