socket programming:using inet_addr() and ip address isn't be hardcoded - c

I use inet_addr() in my program but I don't want the ip address is hardcoded.
so I try inet_addr(argv[1]) but my program fail to get ip address. Can anyone help me?
server
int main(int argc,char *argv[])
{
char str[100]; // declare necessary variables
int listen_fd, comm_fd;
struct sockaddr_in servaddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
char welcome[100];
char i[100];
char incorrectnum[100];
char line[512],line1[500],line2[500],line3[500],line4[500],line5[500];
FILE *fp;
char ch;
char str2[100];
char *file_path = "FILE.txt";
listen_fd = socket(AF_INET, SOCK_STREAM, 0); //create a socket
if (listen_fd == -1)
{
printf("Could not create socket");
}
puts("Socket created");
strcpy(str2,argv[1]);
printf("%s\n",str2 );
servaddr.sin_family = AF_INET; // prepare the sockaddr_in structure.
servaddr.sin_port = htons(1999);
servaddr.sin_addr.s_addr = inet_addr(str2);
memset(servaddr.sin_zero, '\0', sizeof servaddr.sin_zero);
if(bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr))<0){ //bind a name to a socket
//print the error message
perror("bind failed. Error");
return 1;
}
puts("bind done");
listen(listen_fd, BACKLOG); //listening for incomming connection
puts("Waiting for incoming connections...");
addr_size = sizeof serverStorage;
comm_fd = accept(listen_fd, (struct sockaddr *)&serverStorage, &addr_size);
if (comm_fd < 0){
perror("accept failed");
return 1;
}
puts("Connection accepted");
printf("***___WELCOME TO MY SERVER___***\n");
bzero(welcome, 100);
strcpy(welcome,"***___WELCOME TO MY SERVER___***");
send(comm_fd, welcome,100, 0);
.....
}
client
int main(int argc,char *argv[]){
int sockfd, linenum; //declare necessary variables
char str[100];
char i[100];
char server_respose[2000],line1[1000],line2[1000],line3[1000],line4[1000],line5[1000];
char welcome[100];
struct sockaddr_in servaddr; // socket address struct
if(argc != 2)
{
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
sockfd = socket(AF_INET, SOCK_STREAM, 0); //create a socket with the appropriate protocol
if (sockfd == -1)
{
printf("Could not create socket\n");
}
puts("Socket created");
servaddr.sin_family = AF_INET; //IPv4
servaddr.sin_port = htons(1999);
memset(servaddr.sin_zero, '\0', sizeof servaddr.sin_zero);
servaddr.sin_addr.s_addr = inet_addr(argv[1]);
if(connect(sockfd,(struct sockaddr *)&servaddr, sizeof(servaddr))<0){
perror("connect failed. Error");
return 1; // attempt to connect to a socket
}
printf("--You are connected to the server--\n");
recv(sockfd, welcome, 100, 0)
...
}

inet_addr should be avoided in new programs, in favour of (among other methods) getaddrinfo. This method is IPv6 compatible and generally easier to use.
The linux.die.net page has a good code sample for client/server communication which does exactly what you're looking for: http://linux.die.net/man/3/getaddrinfo (important parts reproduced below)
Server program
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
int main(int argc, char *argv[]) { // port
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, s;
if (argc != 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
s = getaddrinfo(NULL, argv[1], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully bind(2).
If socket(2) (or bind(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sfd == -1)
continue;
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
break; /* Success */
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not bind\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(result); /* No longer needed */
// ...snip - not relevant to this question
}
Client program
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[]) { // host port
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, s, j;
if (argc < 3) {
fprintf(stderr, "Usage: %s host port msg...\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Obtain address(es) matching host/port */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
s = getaddrinfo(argv[1], argv[2], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully connect(2).
If socket(2) (or connect(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sfd == -1)
continue;
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
break; /* Success */
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(result); /* No longer needed */
// ...snip - not relevant to this question
exit(EXIT_SUCCESS);
}

Related

getaddrinfo linux manpage server example but using TCP instead of UDP

I'm trying to convert the server program example from getaddrinfo's linux manpage from UDP to TCP.
When running the program without any change first, I can communicate with a netcat client using UDP :
gcc main.c
./a.out 1234
netcat -u 127.0.0.1 1234
// this works here, I can send messages to the server
Then if I try with TCP :
netcat 127.0.0.1 1234
^ this doesn´t connect and exists directly
I tried to change some attributes in the addrinfo struct :
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* Stream socket */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
And it doesn´t connect either.
Here is the whole code :
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#define BUF_SIZE 500
int
main(int argc, char *argv[])
{
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, s;
struct sockaddr_storage peer_addr;
socklen_t peer_addr_len;
ssize_t nread;
char buf[BUF_SIZE];
if (argc != 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* Stream socket */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
s = getaddrinfo(NULL, argv[1], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully bind(2).
If socket(2) (or bind(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sfd == -1)
continue;
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
break; /* Success */
close(sfd);
}
freeaddrinfo(result); /* No longer needed */
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not bind\n");
exit(EXIT_FAILURE);
}
/* Read datagrams and echo them back to sender */
for (;;) {
peer_addr_len = sizeof(peer_addr);
nread = recvfrom(sfd, buf, BUF_SIZE, 0,
(struct sockaddr *) &peer_addr, &peer_addr_len);
if (nread == -1)
continue; /* Ignore failed request */
char host[NI_MAXHOST], service[NI_MAXSERV];
s = getnameinfo((struct sockaddr *) &peer_addr,
peer_addr_len, host, NI_MAXHOST,
service, NI_MAXSERV, NI_NUMERICSERV);
if (s == 0)
printf("Received %zd bytes from %s:%s\n",
nread, host, service);
else
fprintf(stderr, "getnameinfo: %s\n", gai_strerror(s));
if (sendto(sfd, buf, nread, 0,
(struct sockaddr *) &peer_addr,
peer_addr_len) != nread)
fprintf(stderr, "Error sending response\n");
}
}
How to make this server program accept TCP connections with netcat ?

IPv6 client cannot connect to IPv6 server, cannot assign requested address

Re-using code here to reproduce a tcp client/server interaction.
The server initializes fine, begins listening for connections.
However, on running client ./client, the client fails with message
connect(): Cannot assign requested address
where the "failing" code from the link above (and also pasted below) is:
ret = connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (ret == -1) {
perror("connect()");
close(sock_fd);
return EXIT_FAILURE;
}
When I run ifconfig, I do not see an IPv6 address. Is this a possible explanation? I am running an Ubuntu Docker image on an OSX machine.
The code is easily compilable/runnable with
gcc server.c -o server
gcc client.c -o client
./server
./client
server.c
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#define CLIENT_QUEUE_LEN 10
#define SERVER_PORT 7002
int main(void)
{
int listen_sock_fd = -1, client_sock_fd = -1;
struct sockaddr_in6 server_addr, client_addr;
socklen_t client_addr_len;
char str_addr[INET6_ADDRSTRLEN];
int ret, flag;
char ch;
/* Create socket for listening (client requests) */
listen_sock_fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
if(listen_sock_fd == -1) {
perror("socket()");
return EXIT_FAILURE;
}
/* Set socket to reuse address */
flag = 1;
ret = setsockopt(listen_sock_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
if(ret == -1) {
perror("setsockopt()");
return EXIT_FAILURE;
}
server_addr.sin6_family = AF_INET6;
server_addr.sin6_addr = in6addr_any;
server_addr.sin6_port = htons(SERVER_PORT);
/* Bind address and socket together */
ret = bind(listen_sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(ret == -1) {
perror("bind()");
close(listen_sock_fd);
return EXIT_FAILURE;
}
/* Create listening queue (client requests) */
ret = listen(listen_sock_fd, CLIENT_QUEUE_LEN);
if (ret == -1) {
perror("listen()");
close(listen_sock_fd);
return EXIT_FAILURE;
}
client_addr_len = sizeof(client_addr);
while(1) {
/* Do TCP handshake with client */
client_sock_fd = accept(listen_sock_fd,
(struct sockaddr*)&client_addr,
&client_addr_len);
if (client_sock_fd == -1) {
perror("accept()");
close(listen_sock_fd);
return EXIT_FAILURE;
}
inet_ntop(AF_INET6, &(client_addr.sin6_addr),
str_addr, sizeof(str_addr));
printf("New connection from: %s:%d ...\n",
str_addr,
ntohs(client_addr.sin6_port));
/* Wait for data from client */
ret = read(client_sock_fd, &ch, 1);
if (ret == -1) {
perror("read()");
close(client_sock_fd);
continue;
}
/* Do very useful thing with received data :-) */
ch++;
/* Send response to client */
ret = write(client_sock_fd, &ch, 1);
if (ret == -1) {
perror("write()");
close(client_sock_fd);
continue;
}
/* Do TCP teardown */
ret = close(client_sock_fd);
if (ret == -1) {
perror("close()");
client_sock_fd = -1;
}
printf("Connection closed\n");
}
return EXIT_SUCCESS;
}
client.c
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#define SERVER_PORT 7002
int main(int argc, char *argv[])
{
int sock_fd = -1;
struct sockaddr_in6 server_addr;
int ret;
char ch = 'a';
/* Arguments could be used in getaddrinfo() to get e.g. IP of server */
(void)argc;
(void)argv;
/* Create socket for communication with server */
sock_fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (sock_fd == -1) {
perror("socket()");
return EXIT_FAILURE;
}
/* Connect to server running on localhost */
server_addr.sin6_family = AF_INET6;
inet_pton(AF_INET6, "::1", &server_addr.sin6_addr);
server_addr.sin6_port = htons(SERVER_PORT);
/* Try to do TCP handshake with server */
ret = connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (ret == -1) {
perror("connect()");
close(sock_fd);
return EXIT_FAILURE;
}
/* Send data to server */
ret = write(sock_fd, &ch, 1);
if (ret == -1) {
perror("write");
close(sock_fd);
return EXIT_FAILURE;
}
/* Wait for data from server */
ret = read(sock_fd, &ch, 1);
if (ret == -1) {
perror("read()");
close(sock_fd);
return EXIT_FAILURE;
}
printf("Received %c from server\n", ch);
/* DO TCP teardown */
ret = close(sock_fd);
if (ret == -1) {
perror("close()");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
So when I ran the code on a non docker container (the host) which has an IPv6 address based on running ifconfig, I get the output
Received b from server
which appears to confirm my suspicion that the container does not support IPv6.
If anyone cares to elaborate, they are welcome to.
Your server_addr.sin6_flowspec and other members of that struct are being left uninitialized.
Start by zero'ing out your server_addr instances before passing it to connect.
Either this at declaration time:
struct sockaddr_in6 server_addr = {0};
Or a memset call to fill it with all zeros before you start assigning the members of that struct values.
memset(&server_addr, '\0', sizeof(server_addr));
I believe that will fix your issue. If not, read on.
If the above doesn't resolve your issue, it's likely because you aren't properly initializing the sin6_flowspec or other members of the sockaddr_in6 struct that aren't in the ipv4 sockaddr_in struct. You can leverage getaddrinfo to do the heavy work for you to properly fill in these fields.
int result = 0;
addrinfo* resultList = NULL;
addrinfo hints = {};
hints.ai_family = AF_INET6;
hints.ai_flags |= AI_NUMERICHOST; // comment this line out if getaddrinfo fails
hints.ai_socktype = SOCK_STREAM;
int result = getaddrinfo("::1", NULL, &hints, &resultList);
if ((result == 0) && (resultList->ai_family == AF_INET6))
{
memcpy(&server_addr, resultList->ai_addr, sizeof(sockaddr_in6));
server_addr.sin6_port = htons(SERVER_PORT);
}
else
{
// fail
}
if (resultList)
{
freeaddrinfo(&resultList);
}
resultList = NULL;

The UDP sendto() and recvfrom() functions are not working as expected

I wanted to implement a simple UDP server and client, so I wrote the code halfway in C language.
The purpose of the code is to send a message from the Client to the Server, and if the message is sent correctly, the Server sends an "ACK" message to the Client.
However, the return values of sendto() and recvfrom() are -1, and the message is not sent.
In udpserver.c, I know that "ACK" is firmly overwritten in buf by strcpy.
In udpserver.c, I can send messages and in udpclient.c, I can receive messages, but I don't know how to write code from here. Can you give me some specific code?
Also, I want the server to say Hello, and the client to say ACK.
#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 MYPORT "4567" // the port that client will be connecting to
#define MAXBUFLEN 100
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void)
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
struct sockaddr_storage their_addr;
char buf[MAXBUFLEN];
int32_t receivedNumber;
socklen_t addr_len;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM; // UDP
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
exit(1);
}
printf("server: waiting for client...\n");
addr_len = sizeof their_addr;
//Receive from client
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, (struct sockaddr *)&their_addr, &addr_len)) == -1) {
perror("recvfrom");
exit(1);
}
printf("Received from client: %s\n", buf);
strcpy(buf,"ACK");
//Send client an ACK message
if(sendto(sockfd,buf,strlen(buf),0,p->ai_addr,p->ai_addrlen)==-1){
printf("Error\n");
}
/*
unknown code
*/
freeaddrinfo(servinfo);
close(sockfd);
return 0;
}
#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 "4567" // the port that client will be connecting to
#define MAXBUFLEN 100
int main(int argc, char *argv[])
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr;
socklen_t addr_len;
int rv;
int numbytes;
char buf[MAXBUFLEN];
if (argc != 3) {
fprintf(stderr,"usage: talker hostname message\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to create socket\n");
return 2;
}
// Send to server
if ((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0, p->ai_addr, p->ai_addrlen)) == -1) {
perror("client: sendto");
exit(1);
}
//Receive from server
if(recvfrom(sockfd,buf,MAXBUFLEN-1,0,(struct sockaddr *)&their_addr,&p->ai_addrlen)==-1){
printf("Error\n");
}
/*
unknown code
*/
printf("Received from server: %s\n", buf);
freeaddrinfo(servinfo);
close(sockfd);
return 0;
}
gcc udpserver.c
./a.out
server: waiting for client...
Received from client: Hello~
gcc udpclient.c
./a.out 127.0.0.1 Hello
Received from server: �*��z ```
If you read from a channel into a buffer and the result is positive, then you have successfully read some bytes, but not a null-terminated string.
e.g.
numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1, ...);
numbytes is the number of bytes read, now it is time to make a string:
buf[numbytes] = '\0';
Both the client and server do not add the null-byte to the end of buf.

Server and client program not sending or receiving data

I've been scratching my head with this one for quite a while now. I've got a simple client and server program and I want the server to echo what the client sends it. I can't figure out why the server isn't receiving any data.
Client code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_BUF 64
#define MAX_ARGS 8
void initClient(int*);
int main()
{
int socket;
/* initialize socket and connect to server */
initClient(&socket);
while(1){
char in[80];
char temp[80];
bzero(in, 80);
bzero(temp, 80);
printf("What's your message: ");
gets(in);
strcpy(temp, in);
send(socket, temp, strlen(temp), 0);
if(strcmp(temp, "exit") == 0)
break;
}
return 0;
}
void initClient(int *sock)
{
FILE *configFile;
char ip[MAX_BUF];
int port;
int i;
struct sockaddr_in addr;
/* get IP address and port number from config file */
if (!(configFile=fopen(".config","r"))) {
printf("cannot read config file...\n");
exit(1);
}
fscanf(configFile, "%s", ip);
fscanf(configFile, "%d", &port);
fclose(configFile);
/* create socket and connect to logger */
sock = (int *)socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sock < 0){
printf("Could not open socket\n");
exit(-1);
}
/* setup address */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons((unsigned short) port);
/* connect to server */
i = connect((int)sock,
(struct sockaddr *) &addr,
sizeof(addr));
if (i<0) {
printf("client could not connect!\n");
exit(-1);
}
}
Server code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_BUF 64
int main()
{
FILE *configFile;
char ip[MAX_BUF];
int port;
char str[MAX_BUF];
/* get IP address and port number from config file */
if (!(configFile=fopen(".config","r"))) {
printf("cannot read config file...\n");
exit(1);
}
fscanf(configFile, "%s", ip);
fscanf(configFile, "%d", &port);
fclose(configFile);
int myListenSocket, clientSocket;
struct sockaddr_in myAddr, clientAddr;
int i, addrSize, bytesRcv;
/* Create socket */
myListenSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(myListenSocket < 0) {
printf("Couldn't open socket\n");
exit(-1);
}
/* Set up server address */
memset(&myAddr, 0, sizeof(myAddr));
myAddr.sin_family = AF_INET;
myAddr.sin_addr.s_addr = htonl(INADDR_ANY);
myAddr.sin_port = htons((unsigned short) port);
/* Binding */
i = bind(myListenSocket, (struct sockaddr *) &myAddr, sizeof(myAddr));
if(i < 0){
printf("Couldn't bind socket\n");
exit(-1);
}
/* Listen */
i = listen(myListenSocket, 5);
if(i < 0){
printf("Couldn't listen\n");
exit(-1);
}
/* Wait for connection request */
addrSize = sizeof(clientAddr);
clientSocket = accept(myListenSocket,
(struct sockaddr *) &clientAddr,
&addrSize);
if(clientSocket < 0){
printf("Couldn't accept the connection\n");
exit(-1);
}
/* Read message from client and do something with it */
char buffer[100];
while(1){
bzero(buffer, 100);
bytesRcv = read(clientSocket, buffer, sizeof(buffer));
buffer[bytesRcv] = 0;
printf("this is what the client sent: %s\n", buffer);
if(bytesRcv == 0){
break;
}
}
close(myListenSocket);
close(clientSocket);
return 0;
}
When you pass a pointer you should reference it as *sock to get its value, otherwise if you reference it as sock you are, in fact, getting the address and not the value of the variable.
Here is your initClient function corrected:
void initClient(int *sock)
{
FILE *configFile;
char ip[128];
int port;
int i;
struct sockaddr_in addr;
/* get IP address and port number from config file */
if (!(configFile=fopen(".config","r"))) {
printf("cannot read config file...\n");
exit(1);
}
fscanf(configFile, "%s", ip);
fscanf(configFile, "%d", &port);
fclose(configFile);
/* create socket and connect to logger */
*sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(*sock < 0){
printf("Could not open socket\n");
exit(-1);
}
/* setup address */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons((unsigned short) port);
/* connect to server */
i = connect(*sock, (struct sockaddr *) &addr, sizeof(addr));
if (i<0) {
printf("client could not connect!\n");
exit(-1);
}
}

sendto() crashes with error code "Success"

My problem is quite infuriating, actually. I'll show you the code first.
/*
** listener.c -- a datagram sockets "server" demo
*/
//Original Code: Brian Hall (beej#beej.us)
//Commented and modified by Vishal Kotcherlakota (PID A07124450)
#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 MYPORT "4960" // the port users will be connecting to
#define YOURPORT "4961"
#define MAXBUFLEN 10000
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
//If the socket address struct says it's an IPv4...
if (sa->sa_family == AF_INET) {
//...return the IPv4 variable.
return &(((struct sockaddr_in*)sa)->sin_addr);
}
//otherwise, assume it's IPv6, and get the IPv6 variable
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(int argc, char *argv[])
{
int sockfd, sockfdAck; //socket file descriptor (handle)
struct addrinfo hints, *servinfo, *p, *q;
int rv;
int numbytes;
unsigned int seqNum, stateNum=0, ackNum;
struct sockaddr_storage their_addr;
struct timeval recvTime, timeStamp, latency;
char buf[MAXBUFLEN], junk[MAXBUFLEN];
size_t addr_len;
char *ackBack;
char s[INET6_ADDRSTRLEN];
if (argc != 2)
{
fprintf(stderr, "usage: <executable> <hostname>\n");
exit(0);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(q = servinfo; q != NULL; q = q->ai_next) {
if ((sockfd = socket(q->ai_family, q->ai_socktype,
q->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}
if (bind(sockfd, q->ai_addr, q->ai_addrlen) == -1) {
close(sockfd);
perror("listener: bind");
continue;
}
break;
}
if (q == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}
freeaddrinfo(servinfo);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(argv[1], BACKPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfdAck = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}
freeaddrinfo(servinfo);
printf("listener: waiting to recvfrom...\n");
while (1)
{
addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
(struct sockaddr *)&their_addr, &addr_len)) == -1) {
perror("recvfrom");
exit(1);
}
/*printf("listener: got packet from %s\n",
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s));
printf("listener: packet is %d bytes long\n", numbytes);
*/
buf[numbytes] = '\0';
sscanf(buf,"%u %s",&seqNum, junk);
if (seqNum == stateNum + 1)
{
stateNum = seqNum;
printf("Ok, state is now %u.\n", stateNum);
}
ackBack = malloc(20*sizeof(char));
sprintf(ackBack, "%u acknowledged\0", stateNum);
numbytes = sendto(sockfdAck, ackBack, strlen(ackBack), 0, p->ai_addr, p->ai_addrlen);
if (numbytes == -1);
{
perror("sendto");
exit(1);
}
free(ackBack);
}
return 0;
}
Please forgive the sloppy code; I'm desperately trying to finish this assignment on time. The goal is to develop an ARQ protocol using datagram sockets. This code should work, but when I run it, I get an error sendto: Success, meaning that my sendto() call failed. I can't find documentation for this anywhere, and I'm getting to be extremely desperate.
It has nothing to do with having to bind() - in fact take a look at this syntax:
if (numbytes == -1) ; // semicolon !
{
perror("sendto");
exit(1);
}
You have a condition without the body, and then the body without the condition, which always executes (as you can observe).
Add the printf of numbytes and you will see it is set correct, there is no error.
To avoid this kind of hard-to-see errors, I generally put the opening brace immediately after the condition - then you would have spotted this immediately. But of course this is a matter of the coding convention for the company/project.

Resources