Good evening to all,
For kicks and giggles I'm trying my hand at *NIX sockets and TCP/IP. Now, to get off the ground I'm simply trying to create a socket on two endpoints and a basic text chat program back and forth. Now, before I'm even up and running I'm hit with a bind 'Invalid Argument':
user#user-VirtualBox:~/sockets$ ./socket
sock=3
s_->sin_family = 2
s_->sin_port = 3879
s_->sin_addr.s_addr = 0
sockfd = 3
s_->sin_family = 2
s_->sin_port = 3879
s_->sin_addr.s_addr = 0
Socket bind error: Invalid argument
sizeof(s_) = 8
Code below. so, INADDR_ANY should be 255.255.225.255 = 0, from what I understand; AF_INET is 2; and sin_port, well, I've looked at the binary backward and forward and am not sure I understand how 9000 is represented in host order at 3879 from 9000, but assume it's a non-issue. Additionally, since 1 is stdout and 2 is stderr, I assume that anything above this is dynamically allocated and so 3 should be fine for the socket file descriptor.
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
void setSocket(struct sockaddr_in* s_){
s_->sin_family=AF_INET;
s_->sin_port=htons(9999);
s_->sin_addr.s_addr=INADDR_ANY;
memset(&(s_->sin_zero), '\0', 8);
printf("s_->sin_family = %i\n", s_->sin_family);
printf("s_->sin_port = %i\n", s_->sin_port);
printf("s_->sin_addr.s_addr= %i\n", s_->sin_addr.s_addr);
}
void createSocket(int *sock){
if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) == -1){
fprintf(stderr, "Socket creation error: %s\n", strerror(errno));
exit(1);
}
printf("sock = %i\n", *sock);
fflush(stdout);
}
void bindSocket(int sock, struct sockaddr_in* s_){
printf("s_->sin_family = %i\n",s_->sin_family);
printf("s_->sin_port = %i\n",s_->sin_port);
printf("s_->sin_addr.s_addr = %i\n",s_->sin_addr.s_addr);
if((bind(sock, (struct sockaddr*)s_, (socklen_t)sizeof(s_))) == -1){
fprintf(stderr, "Socket bind error: %s\n", strerror(errno));
}
printf("sizeof(s_) = %lu\n", sizeof(s_));
}
int main(int argc, char* argv[]){
int sockfd;
struct sockaddr_in socket_;
createSocket(&sockfd);
setSocket(&socket_);
printf("sockfd = %i\n", sockfd);
fflush(stdout);
bindSocket(sockfd, &socket_);
exit(0);
}
I believe the problem is the
sizeof()
inside your bind()... 's_' is a pointer, so its sizeof is (probably) 4...
You need to dereference it:
if((bind(sock, (struct sockaddr*)s_, (socklen_t)sizeof(*s_))) == -1){
fprintf(stderr, "Socket bind error: %s\n", strerror(errno));
}
Related
Spending way too much time trying to figure out why inet_ntop is always returning the same IP address of 2.0.19.86 inside of my barebones C UDP socket program.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define SERVERPORT "4950" // the port users will be connecting to
int main(int argc, char *argv[])
{
int sock;
struct addrinfo addr_type, *server_info, *p;
int err;
int numbytes;
if (argc != 3) {
fprintf(stderr,"usage: talker hostname message\n");
exit(1);
}
//Specify type of response we want to git
memset(&addr_type, 0, sizeof addr_type);
addr_type.ai_family = AF_INET; // set to AF_INET to use IPv4
addr_type.ai_socktype = SOCK_DGRAM;
//Get the address info (like IP address) and store in server_info struct
if ((err = getaddrinfo(argv[1], SERVERPORT, &addr_type, &server_info)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
return 1;
}
// There might be multiple IP addresses...loop through and use the first one that works
for(p = server_info; p != NULL; p = p->ai_next) {
if ((sock = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("Error when creating socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "Client failed to create socket\n");
return 2;
}
char s[INET_ADDRSTRLEN];
inet_ntop(AF_INET,(struct sockaddr_in *)p->ai_addr,s, sizeof s);
printf("sending to %s....\n",s);
if ((numbytes = sendto(sock, argv[2], strlen(argv[2]), 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("Error sending message");
exit(1);
}
printf("client sent %d bytes to %s\n", numbytes, argv[1]);
freeaddrinfo(server_info);
close(sock);
return 0;
}
The lines I am particularly stuck on is:
char s[INET_ADDRSTRLEN];
inet_ntop(AF_INET,(struct sockaddr_in *)p->ai_addr,s, sizeof s);
printf("sending to %s....\n",s);
For example I run the program with ./client www.google.com hello and get the following:
sending to 2.0.19.86....
client sent 5 bytes to www.google.com
I run the program again with ./client localhost hello and inet_ntop still returns the same IP.
sending to 2.0.19.86....
client sent 5 bytes to localhost
No errors are being thrown when I am creating the socket, and the message sends successfully when I send it to the receiving program over localhost, why is inet_ntop still outputting this weird address?
In your call to inet_ntop:
inet_ntop(AF_INET,(struct sockaddr_in *)p->ai_addr,s, sizeof s);
You're not passing in the correct structure. When AF_INET is passed as the first argument, the second argument should have type struct in_addr *, not struct sockaddr_in *.
You need to call out the sin_addr member which is of this type.
inet_ntop(AF_INET, &((struct sockaddr_in *)p->ai_addr)->sin_addr, s, sizeof s);
Trying to get my simple FTP server running. It is running on a remote server. Using cat /etc/*-release reveals the server is running CentOS Linux 7 core.
Referenced: http://pubs.opengroup.org/onlinepubs/9699919799/, specifically:
Specifies a socket that was created with socket(), has been bound to an address with bind(), and has issued a successful call to listen().
My program successfully calls socket, bind, and listen - then accept fails on the server. On OSX 10.11.5 it works just fine (after commenting out a few headers).
I am compiling remotely with gcc -std=c11 ftserver.c -o ftserver. Using logging and stderr I get the following from execution to it throwing exit(1).
Logging output (edit):
ftserver 30000 <-- start the server on port 30000
socket() succeeded with sockfd = 3
bind() succeeded with sockfd = 3
listen() succeeded with sockfd = 3
Server open on 30000
ERROR: Obtaining new socket descriptor with
sockfd = 0
temp_sockfd = -1
errno = 88
Here is the code from the programs entry point to the line that throws the error.
int main (int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: ftserver <port number>\n");
exit(1);
}
int port = atoi(argv[1]);
char client_hostname[STRING_LENGTH];
bzero(client_hostname, STRING_LENGTH);
// set up the server's socket
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {
fprintf(stderr, "[ ERROR ] :: main() :: Failure to assign sockfd");
exit(1);
}
else {
printf("socket() succeeded with sockfd = %d\n", sockfd);
}
// fill the client socket address struct
struct sockaddr_in addr_client;
addr_client.sin_family = AF_INET;
addr_client.sin_port = htons(port);
addr_client.sin_addr.s_addr = INADDR_ANY;
bzero(&(addr_client.sin_zero), 8);
if (bind(sockfd, (struct sockaddr*)&addr_client, sizeof(struct sockaddr)) == -1 ) {
fprintf(stderr, "[ ERROR ] :: main() :: Failure to bind port %d. Please select another port\n", port);
exit(1);
}
else {
printf("bind() succeeded with sockfd = %d\n", sockfd);
}
if (listen(sockfd, QUEUE) == -1) {
fprintf(stderr, "[ ERROR ] :: main() :: Failure to listen on port %d\n", port);
exit(1);
}
else {
printf("listen() succeeded with sockfd = %d\n", sockfd);
}
printf ("Server open on %d\n", port);
struct sigaction signal_action;
signal_action.sa_handler = kill_zombies;
sigemptyset(&signal_action.sa_mask);
signal_action.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &signal_action, NULL) == -1) {
perror("sigaction");
return 1;
}
else {
printf("sigaction succeeded\n");
}
struct sockaddr_in addr_server;
int temp_sockfd;
while (1) {
socklen_t sin_size = sizeof(struct sockaddr_in);
// accept() is used to connection to a client
if ((temp_sockfd = accept(sockfd, (struct sockaddr *)&addr_server, &sin_size)) == -1) {
fprintf(stderr, "ERROR: Obtaining new socket descriptor with \n\tsockfd = %d\n\ttemp_sockfd = %d\n\terrno = %d\n", sockfd, temp_sockfd, errno);
exit(1);
}
else {
printf("accept() succeeded\n");
}
// more code that we never have the pleasure to exec
And the headers:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
// includes for server (CentOS) errors
// comment these out to compile locally (OSX)
// fixes error: ‘WNOHANG’ undeclared
#include <sys/wait.h>
// fixes error: ‘SA_RESTART’ undeclared
#include <asm/signal.h>
From the logs you show
sockfd = 0
it is obvious that between the calls to listen() and accept() the FD sockfd gets overwritten (here: to 0).
This most likely dues to undefined behaviour being invoked some where then or before.
The latter most likely dues to passing a not completely initialised struct sigaction to sigaction().
To fix this, properly initialise the struct sigaction for example like this:
struct sigaction signal_action = {0};
Writing the C source below using Unix local sockets I got an error about the address already in use. After having checked man 7 Unix for further informations I tried to create a sub-folder where executing my program (obviously modifying the sun_path field on the current folder) but the error was ever the same.
Is there someone able to help me?
Source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include <errno.h>
#define MAXLEN 128
int main (int argc, char *argv[]){
struct sockaddr_un server;
int serverfd, clientfd;
socklen_t addrsize = sizeof(struct sockaddr_un);
char buff[MAXLEN], *path;
if (argc < 2){
printf("Error: %s [MESSAGE]\n", argv[0]);
return 1;
}
if ((serverfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
printf("Error \"%s\" in socket()\n", strerror(errno));
exit(1);
}
puts("socket()");
server.sun_family = AF_UNIX;
path = strcpy(server.sun_path, "/home/myhome/Dropbox/Sources/C/sub");
printf("[DEBUG]Address bound at %s\n", path);
if ((bind(serverfd, (struct sockaddr*)&server, addrsize)) < 0){
printf("Error \"%s\" in bind()\n", strerror(errno));
exit(1);
}
puts("bind()");
if ((listen(serverfd, 1)) < 0){
printf("Error \"%s\" in listen()\n", strerror(errno));
exit(1);
}
if ((clientfd = accept(serverfd, NULL, &addrsize)) < 0){
printf("Error \"%s\" in accept()\n", strerror(errno));
exit(1);
}
write(clientfd, argv[1], strlen(argv[1]));
read(clientfd, buff, sizeof(buff));
puts(buff);
close(clientfd);
close(serverfd);
return 0;
}
You should unlink() the path file before bind call. You will get this error when file exists during the bind. Either you should ensure to unlink/remove the file before exiting the application or you could always unlink it before bind.
Check man page of bind. Also, note the example given in the man page at the end.
You can try to use the SO_REUSEADDR flag like so:
int yes = 1;
if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
// error handling
exit(1);
}
I'm trying make asynchronous server listener with C++ .I can write simple listener without asynchronous but now i have problem with CreateThread.
For example if client has been connected console gives me result about this + sniffer can fix it, after 10 sec client must send me again same packet with different data. my console does not gives me result about that packet but sniffer can see that packet... please if anyone can see my problem explain me.
#include <winsock2.h>
#include <windows.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
DWORD WINAPI SocketHandler(void*);
int main(int argv, char** argc){
//The port you want the server to listen on
int host_port = 7878;
//Initialize socket support WINDOWS ONLY!
unsigned short wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 || ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )) {
fprintf(stderr, "Could not find useable sock dll %d\n",WSAGetLastError());
}
//Initialize sockets and set any options
int hsock;
int * p_int ;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if(hsock == -1){
printf("Error initializing socket %d\n",WSAGetLastError());
}
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
(setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
printf("Error setting options %d\n", WSAGetLastError());
free(p_int);
}
free(p_int);
//Bind and listen
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET ;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = INADDR_ANY ;
if( bind( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",WSAGetLastError());
}
if(listen( hsock, 10) == -1 ){
fprintf(stderr, "Error listening %d\n",WSAGetLastError());
}
//Now lets to the server stuff
int* csock;
sockaddr_in sadr;
int addr_size = sizeof(SOCKADDR);
while(true){
printf("waiting for a connection\n");
csock = (int*)malloc(sizeof(int));
if((*csock = accept( hsock, (SOCKADDR*)&sadr, &addr_size))!= INVALID_SOCKET ){
printf("Received connection from %s",inet_ntoa(sadr.sin_addr));
CreateThread(0,0,&SocketHandler, (void*)csock , 0,0);
}
else{
fprintf(stderr, "Error accepting %d\n",WSAGetLastError());
}
}
}
DWORD WINAPI SocketHandler(void* lp){
int *csock = (int*)lp;
char buffer[1024];
int buffer_len = 1024;
int bytecount;
memset(buffer, 0, buffer_len);
if((bytecount = recv(*csock, buffer, buffer_len, 0))==SOCKET_ERROR){
fprintf(stderr, "Error receiving data %d\n", WSAGetLastError());
}
printf("Received bytes %d\n Received string \"%s\"\n", bytecount, buffer);
char buff[1] = {0x11};
if((bytecount = send(*csock, buff, 1, 0))==SOCKET_ERROR){
fprintf(stderr, "Error sending data %d\n", WSAGetLastError());
}
printf("Sent bytes: %d. Send Message: %s\n ", bytecount,buff);
free(csock);
}
A race condition is most likely the cause of your problem. You declare csock on the stack and then pass it to SocketHandler. The trouble is, it's quite possible that the value of csock changes before SocketHandler gets it and makes a copy since csock = accept() is in a loop. The solution is to dynamically allocate csock using malloc and then have SocketHandler free it.
Even if this isn't the cause of your specific problem, this code can never be reliable until you fix that.
CreateThread doesn't loop or anything. You need to put the code in there inside a loop. Something like this:
DWORD WINAPI SocketHandler(void* lp) {
for(;;) {
/* Code here */
}
return EXIT_SUCCESS;
}
I have a C function to check a host and its port, when I use FQDN host name, the function return error like: connect() failed: connect time out, but if I use IP address instead, it seems ok, how to fix this?
Thanks.
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
int is_network_up(char *chkhost, unsigned short chkport) {
int sock;
struct sockaddr_in chksock;
struct hostent *host = NULL;
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
syslog(LOG_ERR, "socket() creation error: %s", strerror(errno));
return 0;
}
memset(&chksock, 0, sizeof(chksock));
chksock.sin_family = AF_INET;
chksock.sin_port = htons(chkport);
/* get the server address */
if (inet_pton(AF_INET, chkhost, &(chksock.sin_addr.s_addr)) <= 0) {
if ((host = gethostbyname(chkhost)) == NULL) {
syslog(LOG_ERR, "%s", hstrerror(h_errno));
return 0;
}
memcpy(&(chksock.sin_addr.s_addr), &(host->h_addr_list[0]),
sizeof(struct in_addr));
}
/* try to connect */
if (connect(sock, (struct sockaddr *) &chksock, sizeof(chksock)) < 0) {
syslog(LOG_ERR, "connect() failed: %s", strerror(errno));
return 0;
}
close(sock);
return 1;
}
inet_pton() is the wrong task for that. It only accepts numerical addresses.
In former times, people used to use gethostbyname() for name resolution.
But as we have 2012 meanwhile, this method is outdated for several years now, as it is still restricted to AF_INET.
With the program below, you should achieve about the same and stay future compatible.
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
int is_network_up(char *chkhost, unsigned short chkport) {
int sock = -1;
struct addrinfo * res, *rp;
int ret = 0;
char sport[10];
snprintf(sport, sizeof sport, "%d", chkport);
struct addrinfo hints = { .ai_socktype=SOCK_STREAM };
if (getaddrinfo(chkhost, sport, &hints, &res)) {
perror("gai");
return 0;
}
for (rp = res; rp && !ret; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sock == -1) continue;
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) {
char node[200], service[100];
getnameinfo(res->ai_addr, res->ai_addrlen, node, sizeof node, service, sizeof
service, NI_NUMERICHOST);
printf("Success on %s, %s\n", node, service);
ret = 1; /* Success */
}
close(sock);
}
freeaddrinfo(res);
return ret;
}
int main(int argc, char** argv) {
if (argc > 1) {
printf("%s: %d\n", argv[1], is_network_up(argv[1], 22));
}
}
Make sure name resolution is working. See if you can ping the machine by name from the exact same environment in which your code runs.
If ping works, try telnet <machinename> <portnumber> -- If both of those work it is likely a problem with your code (which I did not look at in depth, too sleepy:).
Make sure you're converting anything returned by the OS as an ip address from network order to host order. IIRC, gethostbyname returns binary ip addresses in network order.
ntohl can be used on chksock.sin_addr.s_addr after the memcpy to achieve this.