Related
So I have one UDP server that returns the hour or the date to the client with the following code:
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <time.h>
void main(int argc, char *argv[]) {
struct addrinfo hints;
struct addrinfo *res;
struct sockaddr_storage cli;
time_t rawtime;
struct tm* timeinfo;
char tbuffer[9];
char buf[81], host[NI_MAXHOST], serv[NI_MAXSERV];
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 */
getaddrinfo(argv[1], argv[2], &hints, &res);
int sd = socket(res->ai_family, res->ai_socktype, 0);
bind(sd, (struct sockaddr *)res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
while(1) {
socklen_t clen = sizeof(cli);
int c = recvfrom(sd, buf, 80, 0, (struct sockaddr*) &cli, &clen);
buf[c] = '\0';
getnameinfo((struct sockaddr*) &cli, clen, host, NI_MAXHOST, serv, NI_MAXSERV, NI_NUMERICHOST);
time(&rawtime);
timeinfo = localtime(&rawtime);
if(buf[0] == 't') {
printf("%ld bytes de %s:%s\n", c, host, serv);
ssize_t chars = strftime(tbuffer, sizeof(tbuffer), "%T", timeinfo);
sendto(sd, tbuffer, chars, 0, (struct sockaddr *)&cli, clen);
} else if(buf[0] == 'd') {
printf("%ld bytes de %s:%s\n", c, host, serv);
ssize_t chars = strftime(tbuffer, sizeof(tbuffer), "%D", timeinfo);
sendto(sd, tbuffer, chars, 0, (struct sockaddr *)&cli, clen);
} else if(buf[0] == 'q') {
printf("Saliendo...\n");
exit(EXIT_SUCCESS);
} else {
printf("Comando no soportado %s", buf);
}
}
}
To test the code I was using ./server <IPServerAddres> <PortAddress> on the server side and nc -u <IpServerAddress> <PortServer> on the client side (another machine).
Now I want to create the UDP client UDP and do the same without using nc, just writing ./client <IPServerAddres> <PortAddress> <command> where command can be t for time d for date and q for quit, just like in the server.
Here is the code of the client program:
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <time.h>
int main(int argc, char *argv[]) {
struct addrinfo hints;
struct addrinfo *res, *resp;
int sd, j, s;
size_t len;
ssize_t nread, nwrite;
char buf[500];
if (argc < 3) {
fprintf(stderr, "Usage: %s host port command...\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 = 0;
hints.ai_protocol = 0; /* Any protocol */
getaddrinfo(argv[1], argv[2], &hints, &res);
for(resp = res; resp != NULL; resp = resp->ai_next) {
sd = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
if(sd == -1) {
perror("socket()");
continue;
}
if(connect(sd, resp->ai_addr, resp->ai_addrlen) == -1) {
perror("socket()");
} else {
break;
}
close(sd);
}
freeaddrinfo(res);
for(j = 3; j < argc; j++) {
len = strlen(argv[j]) + 1;
nwrite = write(sd, argv[j], len);
if(nwrite == -1) perror("write()");
nread = read(sd, buf, 500);
buf[nread] = 0;
if(nread == -1) perror("read()");
printf("Recibidos %ld bytes: %s\n", (long) nread, buf);
}
exit(EXIT_SUCCESS);
}
The problem is that when I try to run my client program I got no response, so I guess is in a infinite loop or something like that.
Any help will be apreciated, I'm learning C so I'm sorry for the mistakes, thank you.
EDITED: Corrected the break in the for loop in case connect() returns something different than -1.
The problem is in your calculation of the length of the message to send:
len = strlen(argv[j] + 1);
This gets the length of the string starting from the second character. You want:
len = strlen(argv[j]) + 1;
This gives you the string length plus 1 for the null terminator.
Also, after reading the response, you'll need to null-terminate what you got back:
buf[nread] = 0;
I have been trying to learn sockets programming, and came across this website: http://beej.us/guide/bgnet/output/html/multipage/index.html which is really good. I was able to understand, but after writing a test program myself I ended up with a problem which I cannot figure after 3 hours. Have very limited time, so thought asking experts help here.
This is my server program:
/**
* Program showing how sockets can be used
*/
#include <stdio.h> // For printf
#include <strings.h> // For bzero, memset
#include <stdlib.h> // For exit, atoi
#include <unistd.h> // For close
#include <sys/socket.h> // For socket
#include <sys/types.h> // For types
#include <arpa/inet.h> // For inet_addr
#include <netdb.h> // Import module network database
#include <errno.h> // To access the global errno that holds last system call error
#include <assert.h> // For asserting
#define ADDRESSINFO_GET_SUCCESS 0
const int kSuccess = 0;
const char *kMyPort = "3490"; // Can be either port num or name of the service
const int kMaxListenConn = 10; // How many connections queue will hold
// Utility function to get socket address, IPv4 or IPv6:
void* getSocketAddress(const struct sockaddr *sa)
{
// Cast socketaddr to sockaddr_in to get address and port values from data
if (sa->sa_family == PF_INET) {
return &(((struct sockaddr_in *)sa)->sin_addr);
}
return &(((struct sockaddr_in6 *)sa)->sin6_addr);
}
// Utility function to get socket address string
void getSocketAddressString(const struct sockaddr *sd, char *ipAddr)
{
inet_ntop(sd->sa_family, getSocketAddress(sd), ipAddr, INET6_ADDRSTRLEN);
}
int createAndBindSocket(const struct addrinfo *addrList)
{
int status = -1; // Invalid status
int socketFileDesc = -1; // Invalid descriptor
const struct addrinfo *addrIt;
/*
* STEP 2.1: Loop through all the addrinfo nodes and bind to the one we can
*/
for (addrIt = addrList; addrIt != NULL; addrIt = addrIt->ai_next)
{
char ipAddr[INET6_ADDRSTRLEN];
inet_ntop(addrIt->ai_family, getSocketAddress(addrIt->ai_addr), ipAddr, sizeof ipAddr);
printf("IP: %s\n", ipAddr);
/*
* STEP 2.2: Crete the socket file descriptor for our IP address
*/
socketFileDesc = socket(addrIt->ai_family, addrIt->ai_socktype, addrIt->ai_protocol);
if (socketFileDesc == -1) {
fprintf(stderr, "Failed to create socket with error: %d\n", errno);
perror("socket"); // Get error desc
continue; // Try next address
}
/*
* STEP 2.3: Set socket behaviour by making ip address to be re-used if used already
*/
int yes=1;
if (setsockopt(socketFileDesc, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("setsockopt");
exit(1);
}
printf("Port %d\n",((struct sockaddr_in *)addrIt->ai_addr)->sin_port);
/*
* STEP 2.4: Bind our socket with ip address and port number to listen
*/
status = bind(socketFileDesc, addrIt->ai_addr, addrIt->ai_addrlen);
if (status != kSuccess) {
fprintf(stderr, "Failed to bind socket with error:%d\n", errno);
perror("bind"); // Get error desc
// Clear socket
close(socketFileDesc);
socketFileDesc = -1;
continue; // Try next address
}
}
return socketFileDesc;
}
int main()
{
int status = -1; // Status is invalid
struct addrinfo hints; // Holds our hints to get address info
struct addrinfo *addrList; // Contains our address info
/*
* STEP 1: Setup service details
*/
// Make sure struct is empty
bzero(&hints, sizeof hints); // memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; // Don't care IPv4 or v6
hints.ai_socktype = SOCK_STREAM; // Use TCP stream sockets
hints.ai_flags = AI_PASSIVE; // Use my local IPs or you igore this and provide IP manually in first arg
status = getaddrinfo(NULL, kMyPort, &hints, &addrList);
if (status != kSuccess) {
fprintf(stderr, "Failed to get address info with error: %s\n", gai_strerror(status));
exit(1);
}
/*
* STEP 2: Create a socket and bind it
*/
int socketFileDesc;
socketFileDesc = createAndBindSocket(addrList);
freeaddrinfo(addrList); // Done with list
if (socketFileDesc == -1) {
exit(1);
}
/*
* STEP 3: Listen to the port for incoming connections
*/
status = listen(socketFileDesc, kMaxListenConn); // Second arg is number of incoming connections in queue
if (status != kSuccess) {
fprintf(stderr, "Failed to listen to the port\n");
perror("listen");
goto exit;
}
printf("Server is listening at the port %s\n", kMyPort);
struct sockaddr_storage inConnAddr; // Big enough to hold both IPv4 and v6
socklen_t inConnAddrLen = sizeof inConnAddr;
const size_t kMaxBufferSize = 50;
char buff[kMaxBufferSize] = {0};
long bytesReceived = -1;
long bytesSent = 0;
int clientSockfd;
while (1) {
/*
* STEP 4: Accept incoming connections
*/
inConnAddrLen = sizeof inConnAddr;
clientSockfd = accept(socketFileDesc, (struct sockaddr *)&inConnAddr, &inConnAddrLen);
// Got new connection ?
if (clientSockfd == -1) {
perror("accept"); // Print error description
continue; // Continue to look for new connections
}
//
// Got connection, create child process to handle request
//
if (!fork()) {
close(socketFileDesc); // No need with child
char ipAddr[INET6_ADDRSTRLEN];
getSocketAddressString((struct sockaddr *)&inConnAddr, ipAddr);
printf("Child process created for hanlding request from %s\n", ipAddr);
/*
* STEP 5: Receive and Send data to requests
*/
bytesReceived = recv(clientSockfd, &buff, kMaxBufferSize - 1, 0);
if (bytesReceived > 0)
{
printf("Data from client %s\n", buff);
while (bytesSent < bytesReceived) {
bytesSent = send(clientSockfd, buff, bytesReceived, 0);
printf("Bytes sent %ld\n", bytesSent);
}
}
if (bytesReceived < 0) {
perror("recv");
}
else if (bytesReceived == 0) {
printf("Connection closed by server\n");
}
close(clientSockfd); // Close socket
exit(0);
}
}
exit:
/*
* STEP 5: Close the socket
*/
close(socketFileDesc);
return 0;
}
This is my client program:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#include <strings.h>
#include <arpa/inet.h>
const char kSuccess = 0;
// Utility function to get socket address
void* getSocketAddress(const struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &( ((struct sockaddr_in *)sa)->sin_addr );
}
return &( ((struct sockaddr_in6 *)sa)->sin6_addr );
}
// Utility function to get socket address string
void getSocketAddressString(const struct sockaddr *sd, char *ipAddr)
{
inet_ntop(sd->sa_family, getSocketAddress(sd), ipAddr, INET6_ADDRSTRLEN);
}
int createAndConnectSocket(const struct addrinfo *addrList)
{
int socketFileDesc = -1; // Invalid descriptor
const struct addrinfo *addrIt;
/*
* STEP 2.1: Loop through all the addrinfo nodes and bind to the one we can
*/
for (addrIt = addrList; addrIt != NULL; addrIt = addrIt->ai_next)
{
/*
* STEP 2.2: Crete the socket file descriptor for our IP address
*/
socketFileDesc = socket(addrIt->ai_family, addrIt->ai_socktype, addrIt->ai_protocol);
if (socketFileDesc == -1) {
fprintf(stderr, "Failed to create socket with error: %d\n", errno);
perror("socket"); // Get error desc
continue; // Try next address
}
/*
* STEP 2.3: Set socket behaviour by making ip address to be re-used if used already
*/
int yes=1;
if (setsockopt(socketFileDesc, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("setsockopt");
exit(1);
}
char ipAdd[INET6_ADDRSTRLEN];
getSocketAddressString(addrIt->ai_addr, ipAdd);
((struct sockaddr_in *)addrIt->ai_addr)->sin_port = atoi("3490");
printf("IP is %s::%d\n", ipAdd,((struct sockaddr_in *)addrIt->ai_addr)->sin_port);
// Connect to the socket
int status;
status = connect(socketFileDesc, addrIt->ai_addr, addrIt->ai_addrlen);
if (status != kSuccess) {
perror("connect");
close(socketFileDesc);
socketFileDesc = -1;
continue;
}
}
return socketFileDesc;
}
int main(int argc, char* argv[])
{
// Check we have data from arguments
if (argc < 3 || argc > 3) {
perror("Invalid command");
printf("Usage: %s hostname portnumber\n", argv[0]);
printf(" %s 192.168.1.2 3490\n", argv[0]);
}
// Setup server address info
struct addrinfo *serverInfo;
struct addrinfo hints;
int status = -1;
memset(&hints, 0, sizeof hints); // Make sure it is empty
hints.ai_family = AF_INET; // IPv4
hints.ai_socktype = SOCK_STREAM; // Use socket stream
((struct sockaddr_in *)&hints.ai_addr)->sin_port = atoi(argv[2]);
status = getaddrinfo(argv[1], "3490", &hints, &serverInfo);
if (status != kSuccess) {
fprintf(stderr, "Failed to get address info %s\n", gai_strerror(status));
exit(1);
}
printf("Connecting to %s::%s...\n", argv[1], argv[2]);
// Create and bind socket
int sockfd = createAndConnectSocket(serverInfo);
freeaddrinfo(serverInfo); // We are done with serverinfo
if (sockfd == -1) {
exit(1);
}
// Send and receive data from server
long bytesReceived = -1;
long bytesSent = 0;
const size_t kMaxBufferSize = 50;
char buff[kMaxBufferSize];
const char *msg = "Hi! I am client!";
size_t msgLen = strlen(msg);
printf("Connected to server\n");
// Loop to send and receive data
while (1) {
while (bytesSent < msgLen) {
bytesSent = send(sockfd, msg, msgLen, 0);
printf("Bytes sent %ld\n", bytesSent);
}
bytesReceived = recv(sockfd, &buff, kMaxBufferSize - 1, 0);
if (bytesReceived > 0)
{
printf("Data received from server: %s\n", buff);
}
else if (bytesReceived < 0) {
perror("Read error");
break;
}
else if (bytesReceived == 0) {
printf("Connection closed by server\n");
break;
}
}
// Close socket
close(sockfd);
return 0;
}
My problem is: Even though I have set the port and IP in getaddrinfo() call, but when it is binding or connecting the port number found in sockaddr struct is wrong as it is different value. I do know what is happing here, and I get connection refused message when I do that because of that.
Can anyone please take a look at my program and tell me why I am getting connection refused ? I would really appreciate if someone can suggest any improvements in my code.
Thanks
You're not connecting to the port you think you're connecting to.
((struct sockaddr_in *)addrIt->ai_addr)->sin_port = atoi("3490");
The value of sin_port must be in network byte order, i.e. big endian. You're instead assigning the value 3490 (via atoi) directly, so the value is in host byte order. Your platform is most likely using little endian byte ordering.
As a result instead of connecting to port 3490 (0DA2 hex) you're connecting to port 41485 (A2 0D hex).
You need to use the htons function, which converts a 16 bit value (since sin_port is a 16 bit field) from host byte order to network byte order. Also, there's no need to use atoi here. Just use a numeric constant instead.
((struct sockaddr_in *)addrIt->ai_addr)->sin_port = htons(3490);
I am just a beginner in socket programming and currently working on an small program dealing with file transfer using UDP. This program is written in C.
Here is my problem:
UDP server will first use the recvfrom() function to catch message from UDP client so to start sending a file. I sent the file name first, and it couldn't went through, appearing with: Address family not supported by protocol family as the error message(). I checked the sin_family of client_addr, and it is 7. Furthermore, after I tried to set client_addr.sin_family = AF_INET; the server worked fine, except that the client couldn't even receive any message.
I have checked some sources but it happened to be not so helpful, please if anyone knows why and willing to tell. Appreciate all your help.
Below is a short portion of server code:
int socketfd;
/* my address information */
struct sockaddr_in server_addr;
/* connector’s address information */
struct sockaddr_in client_addr;
socklen_t clientLength;
int numbytes;
char buffer[BUFLEN];
int portNum = atoi(port);
time_t timer;
char charfileSize[20];
int percent, count = 0;
struct tm *tm_info;
char timeBuf[30];
if((socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
perror("Server-socket() sockfd error lol!");
exit(1);
} else {
printf("Server-socket() sockfd is OK...\n");
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portNum);
server_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(server_addr.sin_zero), 0, 8);
// bind the socket to the server ip address
if(bind(socketfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
perror("server socket bind to IP error lol!\n");
exit(1);
} else {
printf("successfully bind server ip with socket ...\n");
}
// client_addr.sin_port = htons(portNum);
client_addr.sin_family = AF_INET;
//* for ensuring client connection *//
int tempGet;
char tempBuf[BUFLEN];
//if( (tempGet = recvfrom(socketfd, tempBuf, BUFLEN, 0, (struct sockaddr *)&client_addr, &clientLength)) > 0 ) {
tempGet = recvfrom(socketfd, tempBuf, BUFLEN, 0, (struct sockaddr *)&client_addr, &clientLength);
if( strcmp( tempBuf, "send file" ) == 0) {
printf("Can start transferring file...\n");
}
printf("sin family:%d\n", client_addr.sin_family);
FILE *fp = fopen(filename, "rb");
if ( !fp ) {
perror("Error opening the file\n");
exit(1);
} else {
// successfully opened the file that's going to be transferred
printf("file opened: %s\n", filename);
// get file size
int file_block_size = 0;
bzero(buffer, BUFLEN);
long file_size;
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
// goes back to the beginning of file(fp)
rewind(fp);
printf("file name: %s\n", filename);
printf("file size: %ld kb\n", file_size/1024);
// get time
time(&timer);
clientLength = sizeof(client_addr);
//client_addr.sin_family = AF_INET;
int sendFileName;
// length of file name
if( (sendFileName = sendto(socketfd, filename, strlen(filename), 0, (struct sockaddr *)&client_addr, sizeof(struct sockaddr_in))) >= 0) {
printf("file name sent.\n");
} else {
//printf("%d\n", sendFileName);
perror("file name send error.\n");
exit(1);
}
}
The last argument to recvfrom takes the address of a socklen_t which needs to be initialized with the size of the sockaddr parameter. I don't see clientLength initialized prior to this call, so client_addr is probably not being updated properly when this function returns. This causes the subsequent call to sendto to fail.
If you initialize clientLength before calling recvfrom that will take care of the problem.
clientLength = sizeof(client_addr);
tempGet = recvfrom(socketfd, tempBuf, BUFLEN, 0, (struct sockaddr *)&client_addr, &clientLength);
I am slightly tired of all incorrect and half-correct UDP socket program attempts at Stack Overflow. I have decided to do the reference UDP implementation, taking this question as an example. Next time I see TCP question (and have some time and energy) I will do reference TCP implementation.
This implementation does everything correctly (to the best of my knowledge :). It uses BSD sockets, so Windows implementations will have to make minor changes. Other than that, it should be C-99 conforiming in all.
Errors handling: application checks for possible errors, but does not try to correct them, simply reports. It also is known to leak a socket in certain error conditions (which lead to application shutdown), but adding proper socket close in this case will simply warrant for more code without actually adding a lot of benefit.
Compilation:
gcc -std=c99 -g -D_POSIX_SOURCE -Wall -Werror -pedantic -o test_udp send_udp.c
Usage: ./test_udp server or ./test_udp <hostname> <filename>
Behold: I give you test_udp.c.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
const short port = 4321;
int run_server();
int send_file(const char* const server, const char* const file);
int main(int argc, char* argv[]) {
if (argc < 2 || argc > 3) {
printf("Error: Usage send_udp (server|<server_host>) [<file name>]\n");
return 1;
}
if (!strcmp(argv[1], "server"))
return run_server(); // runs forever
if (argc != 3) {
printf("Error: client mode accepts two arguments: server and file name.\n");
return 1;
}
return send_file(argv[1], argv[2]);
}
int run_server() {
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
printf("run_server(): error creating socket: %s\n", strerror(errno));
return 2;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr))) {
printf("run_server(): error binding socket: %s\n", strerror(errno));
return 2;
}
printf("run_server(): socket created and bound, entering endless loop.\n");
struct sockaddr_in incoming;
socklen_t incoming_sz = sizeof(incoming);
char buff[USHRT_MAX]; // maximum size of UDP datagramm
const char* buff_ptr = buff;
while (1) {
ssize_t msg_size = recvfrom(sock, buff, sizeof(buff), 0, (struct sockaddr*)(&incoming), &incoming_sz);
if (msg_size == -1) {
printf("run_server(): error receiving message: %s\n", strerror(errno));
return 3;
}
if (msg_size == 0) {
printf("run_server(): a message of 0 size received from the client, bogus. Skipping, continue to listen.\n");
continue;
}
// Message structure: unsigned 16 bit length of file name (network order), followed by filename, followed by data
uint16_t fname_len;
if (msg_size < sizeof(fname_len)) {
printf("run_server(): Bogus (too short) message received from the client. Skipping, continue to listen.\n");
continue;
}
memcpy(&fname_len, buff_ptr, sizeof(fname_len));
fname_len = ntohs(fname_len);
buff_ptr += sizeof(fname_len);
msg_size -= sizeof(fname_len);
if (msg_size < fname_len) {
printf("run_server(): Bogus (too short) message received from the client. Skipping, continue to listen.\n");
continue;
}
char file_name[fname_len + 1];
strncpy(file_name, buff_ptr, fname_len);
file_name[fname_len] = '\0';
buff_ptr += fname_len;
msg_size -= fname_len;
printf("run_server(): incoming transfer for file %s, intrinsic file size: %zu\n", file_name, msg_size);
FILE* f = fopen(file_name, "wb");
if (!f) {
printf("run_server(): Could not open file for writing. Skipping the message, carrying on.\n");
continue;
}
size_t written = fwrite(buff_ptr, msg_size, 1, f);
if (written != 1)
printf("run_server(): error, could not write whole file.\n");
else
printf("run_server(): incoming file written successfully.\n");
fclose(f);
}
return 0;
}
int send_file(const char* const server, const char* const file) {
uint16_t fname_len = strlen(file);
uint16_t max_short = 0;
max_short = ~max_short;
if (fname_len > (max_short - sizeof(fname_len))) {
printf("send_file(): file name is toooo large. Can't send this file.\n");
return 2;
}
FILE* f = fopen(file, "rb");
if (!f) {
printf("send_file(): Could not open file for reading. Nothing sent.\n");
return 3;
}
fseek(f, 0, SEEK_END);
unsigned long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
if (fsize > max_short - sizeof(fname_len) - fname_len) {
printf("send_file(): file is toooo large. Can't send this file.\n");
fclose(f);
return 2;
}
char buff[sizeof(fname_len) + fname_len + fsize];
char* buff_ptr = buff;
uint16_t net_fname_len = htons(fname_len);
memcpy(buff_ptr, &net_fname_len, sizeof(net_fname_len));
buff_ptr += sizeof(net_fname_len);
memcpy(buff_ptr, file, fname_len);
buff_ptr += fname_len;
size_t rc = fread(buff_ptr, fsize, 1, f);
if (rc != 1) {
printf("send_file(): Could not read whole file. Error.\n");
fclose(f);
return 3;
}
fclose(f);
struct addrinfo* ainfo;
if (getaddrinfo(server, NULL, NULL, &ainfo) != 0) {
printf("send_file(): Unknown host %s.\n", server);
return 3;
}
struct addrinfo* ainfo_begin = ainfo;
// I will take the first IP v4 entry in possible addressess
while (ainfo->ai_family != AF_INET && ainfo->ai_next)
ainfo = ainfo->ai_next;
if (ainfo->ai_family != AF_INET) {
printf("send_file(): Couldn't resolve host %s to AF_INET address.\n", server);
return 3;
}
int addr = ((struct sockaddr_in*)(ainfo->ai_addr))->sin_addr.s_addr;
freeaddrinfo(ainfo_begin);
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
printf("read_file(): error creating socket: %s\n", strerror(errno));
return 2;
}
struct sockaddr_in remote_addr;
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(port);
remote_addr.sin_addr.s_addr = addr;
ssize_t sent = sendto(sock, buff, sizeof(buff), 0, (struct sockaddr*)(&remote_addr), sizeof(remote_addr));
if (sent != sizeof(buff))
printf("read_file(): error sending message over socket: %s, only %zu bytes sent.\n", strerror(errno), sent);
else
printf("read_file(): file sent successfully.\n");
return sent == sizeof(buff) ? 0 : 3;
}
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);
}
I am reading IPS and PORTS of few Sockets through this text file IP_CONFIG.txt
"192.168.128.3" IP_CSR
"192.168.128.2" IP_HMIR
"192.168.128.1" IP_OBCUR
"192.168.128.4" IP_ASRR
"127.0.0.1" IP_RSOR
"127.0.0.1" IP_RSO_DR
1901 PORT_CSR
1901 PORT_HMIR
1901 PORT_OBCUR
3567 PORT_ASRR
4444 PORT_RSOR
7777 PORT_RSO_DR
I implemented the code with the following way..
1) I saved all different IP addresses in different char strings and Ports with integers.
2) I call these variables when defining socket addresses.
Problem: Although it is giving correct values while calling these variables with printf , but i cann't load these variables while definining IP adrreses and PORTS of different systems
The complete CODE is here.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#define MAX_DATE 100
# define BUFLEN 1024
#define ROW 11
#define COL 2
#define MAXWORDS 24
int main(int argc, char **argv)
{
//Declared variables
int sock, sock_RST; // socket name
int bytes_read; // variable for recvfrom
int addrlen; // length of address
int i = 0, j = 0, k = 0, z = 0; // counters
unsigned char ca[BUFLEN], last_OBCU_msg[BUFLEN], last_HMI_msg[BUFLEN],
rcvd_ASR_msg[BUFLEN]; // Data buffers
struct sockaddr_in server_addr, HMI_addr, OBCU_addr, ASR_addr, RSO_addr,
test_addr; //addresses IP PORT
struct sockaddr_in RSO_addr_d;
const char yes = 1;
int TAG_ASR = 0;
// Create a lof file
time_t now;
char the_date[MAX_DATE];
the_date[0] = '\0';
now = time(NULL );
strftime(the_date, MAX_DATE, "CS_LOG_%H_%M_%d_%m_%Y" ".txt", gmtime(&now));
chdir("/home/bsnayak/CS_LOG/");
FILE *file = fopen(the_date, "a");
//Read IPS and PORTS from a text file
//char* file="C:\\Documents and Settings\\Supernovah\\Desktop\\Supernovah.bin";
//FILE* pFile = fopen( file, "rb" );
char* file_text = "/home/bsnayak/IP_CONFIG.txt";
FILE *fp = fopen(file_text, "r");
int ii = 0, jj;
char *words = NULL, *word = NULL, c;
char *allwords[MAXWORDS];
while ((c = fgetc(fp)) != EOF)
{
ii++;
if (c == '\n')
{
c = ' ';
}
words = (char *) realloc(words, (ii + 1) * sizeof(char));
words[ii - 1] = c;
}
words[ii] = '\0';
word = strtok(words, " ");
ii = 0;
while (word != NULL && ii < MAXWORDS)
{
//printf("%s\n",word);
allwords[ii] = malloc(strlen(word) + 1);
strcpy(allwords[ii], word);
word = strtok(NULL, " ");
//allwords[ii][strlen(word)] = '\0';
ii++;
}
if (error_name)
printf("\nNow printing each saved string:\n");
/*for (jj=0; jj<ii; jj++){
printf("String %d: %s\n", jj, allwords[jj]);
//free(allwords[jj]);
}*/
char *IP_CS = allwords[0];
char *IP_HMI = allwords[2];
char *IP_OBCU = allwords[4];
char *IP_ASR = allwords[6];
char *IP_RSO = allwords[8];
char *IP_RSO_D = allwords[10];
int PORT_CS = atoi(allwords[12]);
int PORT_HMI = atoi(allwords[14]);
int PORT_OBCU = atoi(allwords[16]);
int PORT_ASR = atoi(allwords[18]);
int PORT_RSO = atoi(allwords[20]);
int PORT_RSO_D = atoi(allwords[22]);
//printf("The IPs are \n %s\n %s\n %s\n %s\n %s\n %s\n",IP_CS,IP_HMI,IP_OBCU,IP_ASR,IP_RSO,IP_RSO_D);
//printf("The PORTSs are \n %d\n %d\n %d\n %d\n %d\n %d\n",PORT_CS,PORT_HMI,PORT_OBCU,PORT_ASR,PORT_RSO,PORT_RSO_D);
//free(allwords[MAXWORDS]);
setbuf(stdout, NULL );
addrlen = sizeof(struct sockaddr_in);
// Create the Socket for all connections except RST
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("Socket Creation Error");
exit(1);
}
// Create the Socket for RST section
if ((sock_RST = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("Socket Creation Error");
exit(1);
}
// make CS socket non blocking and reusable
fcntl(sock, F_SETFL, O_NONBLOCK);
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &yes, sizeof(int)) < 0)
{
perror("Reuse option\n");
close(sock);
exit(1);
}
// make RST socket non blocking and reusable
fcntl(sock_RST, F_SETFL, O_NONBLOCK);
if (setsockopt(sock_RST, SOL_SOCKET, SO_REUSEADDR, (char*) &yes, sizeof(int))
< 0)
{
perror("Reuse option\n");
close(sock_RST);
exit(1);
}
printf("\nchecked1\n");
// Control server properties
bzero(&(server_addr.sin_zero), sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT_CS);
server_addr.sin_addr.s_addr = inet_addr(IP_CS); //inet_addr("192.168.128.3"); //
// HMI server properties
bzero(&(HMI_addr.sin_zero), sizeof(HMI_addr));
HMI_addr.sin_family = AF_INET;
HMI_addr.sin_port = htons(PORT_HMI);
HMI_addr.sin_addr.s_addr = inet_addr(IP_HMI);
// OBCU server properties
bzero(&(OBCU_addr.sin_zero), sizeof(OBCU_addr));
OBCU_addr.sin_family = AF_INET;
OBCU_addr.sin_port = htons(PORT_OBCU);
OBCU_addr.sin_addr.s_addr = inet_addr(IP_OBCU);
// ASR Server properties
bzero(&(ASR_addr.sin_zero), sizeof(ASR_addr));
ASR_addr.sin_family = AF_INET;
ASR_addr.sin_port = htons(PORT_ASR);
ASR_addr.sin_addr.s_addr = inet_addr(IP_ASR);
// RSO server properties
bzero(&(RSO_addr.sin_zero), sizeof(RSO_addr));
RSO_addr.sin_family = AF_INET;
RSO_addr.sin_port = htons(PORT_RSO);
RSO_addr.sin_addr.s_addr = inet_addr(IP_RSO);
// RSO destination properties (To which you send string content)
bzero(&(RSO_addr_d.sin_zero), sizeof(RSO_addr_d));
RSO_addr_d.sin_family = AF_INET;
RSO_addr_d.sin_port = htons(PORT_RSO_D);
RSO_addr_d.sin_addr.s_addr = inet_addr(IP_RSO_D);
// BIND Controlserver to the main socket
if (bind(sock, (struct sockaddr *) &server_addr, sizeof(struct sockaddr))
!= 0)
{
perror("Bind Error");
close(sock);
exit(1);
}
printf("checked2\n");
// Bind RSO for second socket
if (bind(sock_RST, (struct sockaddr *) &RSO_addr, sizeof(struct sockaddr))
!= 0)
{
perror("Bind Error");
close(sock_RST);
exit(1);
}
printf("checked3\n");
while (1)
{
addrlen = sizeof(test_addr);
bytes_read = recvfrom(sock, ca, BUFLEN, 0, (struct sockaddr *) &test_addr,
&addrlen);
//printf("checked4\n");
if (test_addr.sin_addr.s_addr == OBCU_addr.sin_addr.s_addr)
{
sendto(sock, ca, bytes_read, 0, (struct sockaddr *) &HMI_addr,
sizeof(HMI_addr));
memcpy(last_OBCU_msg, ca, sizeof(ca));
memset(ca, 0, BUFLEN);
printf("OHS Received\n");
}
}
fclose(file);
return 0;
}
But if i remove the varoable names and assign IP and Ports manually it works perfectly but why cann't use them as variables. Kindly suggest necessary modifications, suggestions..
The IP addresses as read from the file are enclosed by "-signs.
That is you do not pass "1.2.3.4" to inet_addr() but "\"1.2.3.4\"". And as "1.2.3.4" isn't a valid IP address (as 1.2.3.4 would be) the function fails.
Just printing them out or inspecting them using a debugger would have shown you this.