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;
Related
Hello I am working on a school lab in which I have to ask a server to send me a file. Here is my code so far. for some reason, when I run this code, in which I have fixed the arguments for debug purposes, it is as if I get in an infinite loop and get nothing. The problem is surely in gettftp function in the "send" function i think.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <arpa/tftp.h>
#include <sys/socket.h>
#include <netinet/in.h>
int gettftp(const char *fileName, const char *serverIp)
{
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(69);
server_address.sin_addr.s_addr = inet_addr(serverIp);
//sending read request
struct tftphdr *read_request = (struct tftphdr *) malloc(sizeof(struct tftphdr) + strlen(fileName) + 1);
read_request->th_opcode = htons(RRQ);
strcpy(read_request->th_stuff, fileName);
send(sock, read_request, sizeof(struct tftphdr) + strlen(fileName) + 1, 0);
// Receive and save the file
FILE *fp = fopen(fileName, "wb");
while (1) {
char buffer[512];
int bytes_received = recv(sock, buffer, sizeof(buffer), 0);
if (bytes_received < 0) {
break;
}
fwrite(buffer, 1, bytes_received, fp);
}
fclose(fp);
close(sock);
return 0;
}
/**
* Send back the ip address of the requested server
* #param server name inputed right after file to be executed.
* #output none
*/
int main(int argc, char* argv[])
{
char* server, file;
char buffile[100],bufsN[100];
unsigned char ip[50] ="";
struct addrinfo hints, *results, *rp;
int sfd;
argv[1] = "10.10.32.11";
argv[2] = "alt256";
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 */
if(argc<3)
{
printf("You have requested file :\033[0;31m%s\033[0m", argv[2]); //print file name. the part that has 31 changes color to red
printf(" from server : \033[0;31m%s\033[0m \n", argv[1]); //print server name
}
int status = getaddrinfo(argv[1], "69", &hints, &results);
if (status != 0) {
printf("Error: getaddrinfo: %s\n", gai_strerror(status)); //describes what the error does
return 1;
}
else
{
inet_ntop(AF_INET, &results->ai_addr->sa_data[2], ip, sizeof(ip)); //convert ip adress which is part of a struct to string
printf("L'adresse du serveur est: \033[0;31m%s\033[0m \n", ip); //print server ip address
}
for (rp = results; rp != NULL; rp = rp->ai_next) { //socket creation using address family (rp->ai_family), the socket type (ai_socktype)
sfd = socket(rp->ai_family, rp->ai_socktype, //and protocol(ai_protocol)
rp->ai_protocol);
if (sfd == -1) //in case sfd = -1 move on to the next iteration because there is some error somewhere
continue;
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1){ //if connection is successful print message and break out of the oop
printf("Connected to server: \033[0;31m%s\033[0m \n", argv[1] );
break; /* Success */
}
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
//const char* filen = "alt256";
const char* filen = argv[2];
//const char* serverName = "srvtpinfo1.ensea.fr";
strcpy(buffile, filen);
strcpy(bufsN, ip);
gettftp(buffile, bufsN);
//gettftp("alt256", "10.10.32.11");
return 0;
}
}
I have tries debugging to see if the parameters are right when they get in the function and that was the case
I have a piece of C code that should connect to www.google.com and make a HTTP GET request, but when I run it, it stays on "Connecting.." for about 30 seconds before returning "Connection Failed" and an exit return value of 255. What am I doing wrong?
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define PORT 8000
struct hostent *hostinfo;
int main(void) {
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hostname = "www.google.com";
char *request = "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n";
hostinfo = gethostbyname(hostname);
char *ip = inet_ntoa(*(struct in_addr*)hostinfo->h_addr_list[0]);
char buffer[1024] = {0};
printf("Creating socket...\n");
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
printf("Checking address...\n");
if(inet_pton(AF_INET, ip, &serv_addr.sin_addr) <= 0){
printf("\n Invalid IP/Address not supported \n");
return -1;
}
printf("Connecting to host %s...\n", ip);
if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
printf("\n Connection Failed \n");
return -1;
}
send(sock, request, strlen(request), 0);
printf("Message sent\n");
valread = read(sock, buffer, 1024);
printf("%s\n", buffer);
return 0;
}
I see two major problems.
You use the wrong port. Use port 80 for http.
Your read and printf is a dangerous combination that could easily cause access out of bounds (and undefined behavior). What you read from the socket will not be null terminated. You could instead do something like this:
...
printf("Message sent\n");
while((valread = read(sock, buffer, sizeof(buffer))) > 0) {
fwrite(buffer, valread, 1, stdout);
}
This will however block when everything has been read. See non-blocking I/O or consider using select, epoll or poll to wait for available data on sockets.
If you are only interested in getting the response and then disconnect, you could however use Connection: close to close the connection after the server has sent the response. Full code below:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define PORT 80
int main(void) {
int sock = 0, valread;
struct hostent *hostinfo;
struct sockaddr_in serv_addr;
const char *hostname = "www.google.com";
const char *request = "GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: close\r\n\r\n"; // <- added
hostinfo = gethostbyname(hostname);
char *ip = inet_ntoa(*(struct in_addr*)hostinfo->h_addr_list[0]);
char buffer[1024] = {0};
printf("Creating socket...\n");
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
printf("Checking address...\n");
if(inet_pton(AF_INET, ip, &serv_addr.sin_addr) <= 0){
printf("\n Invalid IP/Address not supported \n");
return -1;
}
printf("Connecting to host %s...\n", ip);
if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
perror("connect()");
return -1;
}
send(sock, request, strlen(request), 0);
printf("Message sent\n");
while((valread = read(sock, buffer, sizeof(buffer))) > 0) {
fwrite(buffer, valread, 1, stdout);
}
}
I’ve made C programs they are the server and the client. They send message each other by using udp.
The server waits until message is sent from the client.
When I type some message from the client console, the client will send the message to the server.
The serve receives the message from the client then the server will echo the message on its console and send back same message to the client.
Finaly the client shows message on its console that the server sent back the message.
In this procedure the client shows its source port number on its console.And the server also shows client's source port number that message was sent with recvfrom ()
Strangely, source port number is different between the client and the server if I run them on windows7 but if I run them on CentOS6.4 the source port number is same.
Does anyone know how this happens?
My code are following.
[server]
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
int charToInt(char myText[]) {
char s[] = {'1', '2', '3', '4'};
const int n = strlen(myText);
int i, m = 0;
for(i = 0; i < n; ++ i){
m = m * 10 + myText[i] - '0';
}
printf("%d\n", m);
return m;
}
int
main(int argc,char *argv[])
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
int sock;
struct sockaddr_in addr;
struct sockaddr_in from;
int sockaddr_in_size = sizeof(struct sockaddr_in);
char buf[2048];
char comnd[2048];
char *bye="bye";
printf("############# udpServer start prot number is %d\n",charToInt(argv[1]));
sock = socket(AF_INET, SOCK_DGRAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(charToInt(argv[1]));
addr.sin_addr.s_addr = INADDR_ANY;
bind(sock, (struct sockaddr *)&addr, sizeof(addr));
while (!strncmp(buf,bye,3)==0){
memset(buf, 0, sizeof(buf));
recvfrom(sock, buf, sizeof(buf), 0,(struct sockaddr *)&from, &sockaddr_in_size);
printf("recived '%s'(%d) from %s:%d\n", buf, strlen(buf),
inet_ntoa(from.sin_addr),ntohs(from.sin_port));
sendto(sock, buf, sizeof(buf), 0, (struct sockaddr *)&from, sizeof(from));
printf("send back %s to %s:%d\n", buf,inet_ntoa(from.sin_addr),ntohs(from.sin_port));
printf("\n");
}
printf("bye now");
close(sock);
return 0;
}
[client]
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
#include <errno.h>
int charToInt(char myText[]) {
char s[] = {'1', '2', '3', '4'};
const int n = strlen(myText);
int i, m = 0;
for(i = 0; i < n; ++ i){
m = m * 10 + myText[i] - '0';
}
printf("%d\n", m);
return m;
}
int getMyPortNum(int sock)
{
struct sockaddr_in s;
socklen_t sz = sizeof(s);
getsockname(sock, (struct sockaddr *)&s, &sz);
return s.sin_port;
}
int
main(int agrc,char *argv[])
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
char *host;
int port;
int sock;
struct sockaddr_in dst_addr = {0};
struct sockaddr_in src_addr = {0};
struct sockaddr_in rcv_addr = {0};
int sockaddr_in_size = sizeof(struct sockaddr_in);
int defPortNum;
char message[2048];
char comnd[2048];
int i;
int ret;
int connect_ret;
int bind_ret;
char *p;
char buf[2048];
host=argv[1];
port=charToInt(argv[2]);
printf("host = %s\n",host);
printf("port = %d\n",port);
sock = socket(AF_INET, SOCK_DGRAM, 0);
dst_addr.sin_family = AF_INET;
dst_addr.sin_addr.s_addr = inet_addr(host);
dst_addr.sin_port = htons(port);
printf("getMyPortNum before bind() is %d\n",ntohs(src_addr.sin_port));
bind_ret = 0;
bind_ret = bind(sock,(struct sockaddr *)&src_addr,sizeof(src_addr));
src_addr.sin_port = getMyPortNum(sock);
printf("Default Client port is %d\n",ntohs(src_addr.sin_port));
if(bind_ret>=0){
printf("bind() error ret = %d:%s\n",bind_ret,strerror(errno));
perror("bind()");
return bind_ret;
}
memset(message, 0, sizeof(message));
memset(comnd, 0, sizeof(comnd));
memset(buf,0,sizeof(buf));
while(!strncmp(comnd,"bye",3)==0){
if(strncmp(message,"bye",3)==0){
strcpy(comnd,message);
}else{
printf("typ your message (exit:stop Client bye:stop server)>>>\t");
fgets(comnd,sizeof(comnd),stdin);
comnd[strlen(comnd) - 1] = '\0';
strcpy(message,comnd);
}
ret = sendto(sock, message, strlen(message), 0,
(struct sockaddr *)&dst_addr, sizeof(dst_addr));
printf("Server port (dst port) for sending is %d\n",ntohs(dst_addr.sin_port));
if(ret<0){
printf("Send Error ret = %d:%s\n",ret,strerror(errno));
return ret;
}else{
printf("Waiting for sendBack !!!\n");
printf("Client port for recieving is %s:%d\n"
,inet_ntoa(src_addr.sin_addr),ntohs(src_addr.sin_port));
ret = recvfrom(sock, buf, sizeof(buf),
0,(struct sockaddr *)&rcv_addr, &sockaddr_in_size);
if(ret<0){
printf("ReciveError ret = %d\n",ret);
}else{
printf("Sentback %s from %s:%d\n"
,buf,inet_ntoa(rcv_addr.sin_addr)
,ntohs(rcv_addr.sin_port));
}
}
}
close(sock);
}
It is possible that a new random source port gets used every time you call sendto(), unless you explicitly bind() the client socket to a specific source port (and not rely on the OS doing an implicit bind() for you). That is the only reliable way the client could display its own source port, since sendto() does not report the source port that is actually used. Remember, unlike TCP, UDP is connection-less, so the source port is not required to stay consistent unless you force it.
Update: your client code has one line where it is logging a network byte order port number when it should be logging a host byte order port number instead:
//printf("getMyPortNum before bind() is %d\n",myName.sin_port);
printf("getMyPortNum before bind() is %d\n",port);
Aside from that, why did you create your own charToInt() function, instead of using a standard function, like atoi() or strtol()?
You are also not doing very good error handling.
Try something more like this instead:
[Server]
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int printerror2(char func[], int errnum)
{
printf("%s error = %d:%s\n", func, errnum, strerror(errnum));
perror(func);
return errnum;
}
int printerror(char func[])
{
return printerror2(func, errno);
}
int main(int argc, char *argv[])
{
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(2,2), &wsaData);
if (ret != 0)
return printerror2("WSAStartup()", ret);
int sock;
in_port_t port;
struct sockaddr_in addr;
struct sockaddr_in from;
int from_size;
char buf[2048];
port = atoi(argv[1]);
printf("############# udpServer port number is %hu\n", port);
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == -1)
return printerror("socket()");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if (ret == -1)
return printerror("bind()");
do
{
from_size = sizeof(from);
ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&from, &from_size);
if (ret == -1)
return printerror("recvfrom()");
printf("received '%*s'(%d) from %s:%hu\n",
ret, buf, ret, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
ret = sendto(sock, buf, ret, 0, (struct sockaddr *)&from, from_size);
if (ret == -1)
return printerror("sendto()");
printf("sent back '%*s'(%d) to %s:%hu\n",
ret, buf, ret, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
printf("\n");
}
while ((ret != 3) || (strncmp(buf, "bye", 3) != 0));
printf("bye now");
close(sock);
return 0;
}
[Client]
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int printerror2(char func[], int errnum)
{
printf("%s error = %d:%s\n", func, errnum, strerror(errnum));
perror(func);
return errnum;
}
int printerror(char func[])
{
return printerror2(func, errno);
}
int getMyPortNum(int sock, in_port_t *port)
{
struct sockaddr_in s;
socklen_t sz = sizeof(s);
int ret = getsockname(sock, (struct sockaddr *)&s, &sz);
if (ret == 0)
*port = s.sin_port;
return ret;
}
int main(int agrc, char *argv[])
{
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(2,2), &wsaData);
if (ret != 0)
return printerror2("WSAStartup", ret);
char *host;
in_port_t port;
int sock;
struct sockaddr_in dst_addr;
struct sockaddr_in src_addr;
struct sockaddr_in from_addr;
int from_size;
char buf[2048];
host = argv[1];
port = atoi(argv[2]);
printf("host = %s\n", host);
printf("port = %hu\n", port);
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == -1)
return printerror("socket()");
memset(&src_addr, 0, sizeof(src_addr));
src_addr.sin_family = AF_INET;
src_addr.sin_addr.s_addr = INADDR_ANY;
src_addr.sin_port = 0;
ret = bind(sock, (struct sockaddr *)&src_addr, sizeof(src_addr));
if (ret == -1)
return printerror("bind()");
ret = getMyPortNum(sock, &(src_addr.sin_port));
if (ret == -1)
return printerror("getsockname()");
printf("Client port is %hu\n", ntohs(src_addr.sin_port));
memset(&dst_addr, 0, sizeof(dst_addr));
dst_addr.sin_family = AF_INET;
dst_addr.sin_addr.s_addr = inet_addr(host);
dst_addr.sin_port = htons(port);
do
{
printf("type your message (exit: stop Client, bye: stop server)>>>\t");
fgets(buf, sizeof(buf), stdin);
if (strcmp(buf, "exit") == 0)
break;
ret = sendto(sock, buf, strlen(buf), 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr));
if (ret == -1)
return printerror("sendto()");
printf("Waiting for send back !!!\n");
from_size = sizeof(from_addr);
ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&from_size, &from_size);
if (ret == -1)
return printerror("recvfrom()");
printf("Received '%*s' from %s:%hu\n",
ret, buf, inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port));
}
while ((ret != 3) || (strncmp(buf, "bye", 3) != 0));
close(sock);
return 0;
}
return s.sin_port;
That should be
return ntohs(s.sin_port);
It works in CentOS presumably because 'ntohs(i) == i' there.
I want to make a server that accepts both IPv4 and IPv6 on all interfaces.
It does not seems to work for any address including localhost, 127.0.0.1, ::1, 192.168.1.26.
What am I missing?
According to getaddrinfo(3) since ai_family is set to the AI_PASSIVE flag. 'The returned socket address will contain the "wildcard address"'
Here is my code so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/times.h>
#include <errno.h>
#define MAXBUF 1024
const char* PORTNUM = "687";
int init_address(struct addrinfo* hints)
{
hints->ai_flags= AI_PASSIVE;
hints->ai_family= AF_UNSPEC;
hints->ai_socktype= SOCK_DGRAM;
hints->ai_protocol= IPPROTO_UDP;
return 1;
}
socklen_t init_socket(struct addrinfo* res, int* sockfd)
{
struct addrinfo* ressave;
struct sockaddr_in* all_interface;
socklen_t addrlength;
ressave=res;
all_interface = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
do {/* each of the returned IP address is tried*/
(*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if ((*sockfd)<0)
continue; /* fail, try next one*/
if (bind((*sockfd), (struct sockaddr*)all_interface, sizeof(all_interface)) == 0)
break; /*success*/
close(*sockfd);
}while(res->ai_next != NULL && (res = res->ai_next)!= NULL);
if(&addrlength)
addrlength = res->ai_addrlen;
freeaddrinfo(ressave);
free(all_interface);
return addrlength;
}
int doprocessing(char* buffer, size_t buff_size)
{
return 0;
}
int peak_data(char* buffer, size_t buff_size)
{
return 0;
}
int main(int argc, char const *argv[])
{
int sockfd, newsockfd;
int bytes_read;
char* port;
char buffer[MAXBUF];
pid_t pid;
socklen_t addrlen, len;
struct addrinfo* socket_info;
struct addrinfo* res;
struct addrinfo* backup_res;
struct sockaddr* cliaddr;
int n;
socket_info = (struct addrinfo*)malloc(sizeof(struct addrinfo));
res = (struct addrinfo*)malloc(sizeof(struct addrinfo));
memset(socket_info, 0, sizeof(struct addrinfo));
init_address(socket_info);
if((n = getaddrinfo(NULL, PORTNUM, socket_info, &res)) !=0)
{
printf("multi_server: error for %s: %s", PORTNUM, gai_strerror(n));
exit(0);
}
if ((addrlen = init_socket(res, &sockfd)) < 0)
{
printf("multi_server: Socket or Bind error");
exit(0);
}
free(socket_info);
cliaddr=malloc(addrlen);
len=addrlen;
printf("\nUDP Server: waiting for connection...");
while (1) {
bytes_read = recvfrom(sockfd, buffer, MAXBUF-1, MSG_PEEK, cliaddr, &len);
if (bytes_read > 0) {
// a connection has been established
buffer[MAXBUF] = '\0';
printf("\nUDP Server: received %d bytes ", bytes_read);
pid = fork();
if (pid < 0) {
perror("UDP Server: ERROR while forking new process.\n");
exit(1);
}
// check if the process ID is zero
if (pid == 0) {
// we are now inside the new forked process
if(peak_data(buffer, bytes_read))
{
doprocessing(buffer, bytes_read);
}
printf("Now in %d\n", pid);
close(sockfd);
exit(0);
}
}
}
}
You're not missing anything. It is accepting connections to ::1 you said? Then it will accept ipv6 connections. And since IPv6 is backwards compatible, if you've created the correct ipv6 socket, it should be able to send and receive ipv4 packets as well.
I need to transder a file from one application to another application on the same machine. I wrote code which transfers a packet structure which has fields like:
seq no
round
data, which is an unsigned char indicating the data to be transferred
length, which indicates how many bytes have been read using the read function
crc, which is default string as of now
and a parameter, last, indicating that it is the last packet so that the file and connection can be closed.
This code works perfectly for ASCII files, but, when I use it to transfer a binary file, the diff of two files don't match. I am not able to figure out what the problem is. Can some one help me?
Here is the code for my sender. It connects to receiver on port 4950.
#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 DATA 170
#define SERVERPORT "4950" // the port users will be connecting to
typedef struct packet_ {
unsigned short int seq;
unsigned short int round;
unsigned short int last;
unsigned short int length;
unsigned char data[DATA];
unsigned char crc[17];
} packet;
int main(int argc, char *argv[])
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
int max_seq_no = 10;
packet send;
FILE *fp;
unsigned short int seq =0, round =0;
long int totalBytes = 0;
unsigned short int bytes_read =0;
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;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, 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 bind socket\n");
return 2;
}
fp = fopen("wilde-tiobe.txt", "rb");
printf("Size of packet : %d", sizeof send);
while (1) {
memset((void *) &send, '\0', sizeof send);
send.seq = seq;
send.round = round;
memset(send.data, '\0', DATA);
bytes_read = read(fileno(fp), send.data, DATA );
send.length = bytes_read;
if (bytes_read < DATA) {
send.last = 1;
printf("****last byte***\n");
}
strcpy(send.crc, "yet to calcula\0");
totalBytes+= bytes_read;
//if(bytes_read == 0) break;
if ((numbytes = sendto(sockfd, &send, sizeof send, 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("talker: sendto");
exit(1);
}
usleep(60000);
if (send.last) break;
}
fclose(fp);
printf("Total bytes transferred : %lu\n", totalBytes);
freeaddrinfo(servinfo);
close(sockfd);
return 0;
}
and here is the code for my receiver :
#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 "4950" // the port users will be connecting to
#define MAXBUFLEN 196
#define DATA 170
typedef struct packet_ {
unsigned short int seq;
unsigned short int round;
unsigned short int last;
unsigned short int length;
unsigned char data[DATA];
unsigned char crc[17];
} packet;
// 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;
FILE *fp;
int numbytes;
struct sockaddr_storage their_addr;
char buf[MAXBUFLEN];
socklen_t addr_len;
char s[INET6_ADDRSTRLEN];
packet * recv, recv_packet;
fp = fopen("wtf.bmp", "wb");
printf("size of packet :%d", sizeof(packet));
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(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("listener: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}
freeaddrinfo(servinfo);
addr_len = sizeof their_addr;
while(1) {
printf("listener: waiting to recvfrom...\n");
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN , 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);
//printf("listener: packet contains \"%s\"\n", buf);
recv = (packet *) buf;
if (!recv_packet.data) {
printf("NO memory\n");
break;
}
memset(&recv_packet, 0, sizeof recv_packet);
recv_packet.seq = recv->seq;
recv_packet.round = recv->round;
recv_packet.last = recv->last;
recv_packet.length = recv->length;
memset(recv_packet.data, '\0', DATA);
strncpy(recv_packet.data, recv->data, recv_packet.length);
strncpy(recv_packet.crc, recv->crc, 17);
//printf(" len: %hu and data: %s \n", recv_packet.length, recv_packet.data);
write(fileno(fp), recv_packet.data, recv_packet.length);
if (recv_packet.last) {
printf("Last packet\n");
break;
}
}
fclose(fp);
close(sockfd);
return 0;
}
I already had a similar problem with socket because I was sending a buffer of "unsigned char[]", and receiving into a buffer of "char[]", I dont think is your problem because you do not do any manipulation within the signed array, but any way is good to avoid those casts, and it worth the shot.
use
unsigned char buf[MAXBUFLEN];
instead of
char buf[MAXBUFLEN];
Also clear your buffer before receiving the packet, and check the value of "numbytes" before continuing the process.
Example:
printf("listener: waiting to recvfrom...\n");
memset(buff, 0, sizeof(buff));
numbytes=0;
while ( (numbytes += recvfrom(sockfd, &buf[numbytes], MAXBUFLEN - numbytes , 0,
(struct sockaddr *)&their_addr,
&addr_len)) < sizeof(packet))
printf("Oops, the package is not full, lets read it again.");
}
Or try to pass the MSG_WAITALL flag when using recvfrom to read entire blocks of memory, but I still prefer to check the amount of data read every time.