Retrieving data from a socket client-server transaction - c

I am emulating a client-server socket transaction. Suppose, the client sent some ip packet with
status = send(sock, packet, sizeof(struct iphdr) + sizeof(struct tcphdr),
0);
where sock is the socket, packet points to an ip packet (with ip header struct iphdr and tcp header struct tcphdr)
Now, on the server side, I want to use some function that retrieves the data in packet and displays it. The connection between client and server is correctly set up but when trying to use the recv function, I don't get any data. Is recv the right function
So on the client side I have
packet = malloc(sizeof(struct iphdr)+ sizeof(struct tcphdr));
and I use
send(sock, packet, sizeof(struct iphdr) + sizeof(struct tcphdr),
0);
on the server side, I declared some char packet[32]; and I used this
recv(sock, packet, 32, 0);
Edit 2 - here's the code
On the client side
Edit on the client side (to shorten, I didn't mention the included libraries, the struct iphdr, tcphdr, the in_chksum function, as well I didn't hydrate the tcp header, for now I just want to test)
struct tcphdr tcp_hdr;
struct ip ip_hdr;
#define PORT 23
int sendmeifyoucan(SOCKET sock, SOCKADDR_IN * sin , int size ){
struct ip * ip = (struct ip *)malloc(sizeof(struct ip));
struct tcphdr * tcp;
char * packet;
int sock_err;
int psize=0, status = 1;
packet = malloc(sizeof(struct ip)+ sizeof(struct tcphdr));
memset(packet, 0, sizeof(struct ip) + sizeof(struct tcphdr));
ip->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr) + psize);
ip->ip_hl = 5;
ip->ip_v = 4;
ip->ip_ttl = 255;
ip->ip_tos = 0;
ip->ip_off = 0;
ip->ip_p = IPPROTO_ICMP;
ip->ip_src.s_addr = inet_addr("127.0.0.1");
ip->ip_dst.s_addr = inet_addr("127.0.0.1");
ip->ip_sum = in_chksum((u_short *)ip, sizeof(struct ip));
status = send(sock, packet, sizeof(struct iphdr) + sizeof(struct tcphdr),
0);
free(packet);
return 0;
}
int main(void)
{
int erreur = 0;
SOCKADDR_IN sin;
SOCKET sock;
SOCKADDR_IN csin;
SOCKET csock;
int sock_err;
if(!erreur)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock != INVALID_SOCKET)
{
printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
int size = 0;
/* Configuration */
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
{
printf("Connection à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
sendmeifyoucan(sock, &sin,size);
/* Si l'on reçoit des informations : on les affiche à l'écran */
}
}
printf("Fermeture de la socket client\n");
closesocket(csock);
printf("Fermeture de la socket serveur\n");
closesocket(sock);
printf("Fermeture du serveur terminée\n");
}
else
perror("socket");
}
return EXIT_SUCCESS;
}
On the server side
#define PORT 23
int main(void)
{
int erreur = 0;
SOCKET sock;
SOCKADDR_IN sin;
socklen_t recsize = sizeof(sin);
SOCKADDR_IN csin;
char buffer[32] = "";
int sock_err;
if(!erreur)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock != INVALID_SOCKET)
{
printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
/* Configuration */
csin.sin_addr.s_addr = inet_addr("127.0.0.1");
csin.sin_family = AF_INET;
csin.sin_port = htons(PORT);
sock_err = bind(sock, (SOCKADDR*) &csin, sizeof(csin));
if(sock_err != SOCKET_ERROR)
{
sock_err = listen(sock, 5);
printf("Listage du port %d...\n", PORT);
}
if(sock_err != SOCKET_ERROR)
{
/* Attente pendant laquelle le client se connecte */
printf("Patientez pendant que le client se connecte sur le port %d...\n", PORT);
sock = accept(sock, (SOCKADDR*)&sin, &recsize);
}
if(recv(sock, buffer, 32, 0) != SOCKET_ERROR)
{
printf("Recu : %s\n", buffer);
}
else
{
printf("Impossible de se connecter\n");
}
closesocket(sock);
}
else
perror("socket");
}
return EXIT_SUCCESS;
}
Edit 3 - the headers
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <unistd.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close(s)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
#include <stdio.h>
#include <stdlib.h>
#define PORT 23

Okay now I see your problems.
On client side:
First issue (big):
You are not CONNECTING at all.
where is your connect() call on the client side?
If you want to use SOCK_STREAM you need a connect(2) call
In the code snippet:
if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR) {
printf("Connection à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
/* Si l'on reçoit des informations : on les affiche à l'écran */
}
your sendmeifyoucan() is OUTSIDE the if block { } ;
2nd issue
struct iphdr * ip = (struct iphdr *)malloc(sizeof(struct iphdr *));
should be
struct iphdr * ip = (struct iphdr *)malloc(sizeof(struct iphdr));
Otherwise you are in a stack overflow issue.
Third issue (not so big)
you are allocating char *packet but you are not copying anything on to it it's just memset to 0;
Debug accordingly and try again :)

Related

Could not able to do bidirectional multicast connection using UDP

Have to make it server & client as bidirectional where I should able to send & receive data in console.
I can able to send data from server to client but not able to receive any data from client.Stuck in this for long time could not know how to resolve it.
I just started working on networking any lead on this really helpful.
Here is my code.
Server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
struct in_addr localInterface;
struct sockaddr_in groupSock, rcv_addr;
int sd;
char databuf[1024];
int datalen = sizeof(databuf);
int main(int argc, char *argv[])
{
/* Create a datagram socket on which to send. */
socklen_t rcv_addr_size = sizeof(struct sockaddr_in);
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
else
printf("Opening the datagram socket...OK.\n");
memset((char*) &groupSock, 0, sizeof(groupSock));
groupSock.sin_family = AF_INET;
groupSock.sin_addr.s_addr = inet_addr("226.1.1.1");
groupSock.sin_port = htons(4321);
localInterface.s_addr = inet_addr("127.0.0.1");
if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char*) &localInterface,
sizeof(localInterface)) < 0) {
perror("Setting local interface error");
exit(1);
} else
printf("Setting the local interface...OK\n");
int read_size;
while (1) {
memset(databuf, 0x00, sizeof(databuf));
scanf("%s", databuf);
datalen = strlen(databuf) + 1;
if (sendto(sd, databuf, datalen, 0, (struct sockaddr*) &groupSock,
sizeof(groupSock)) < 0)
datalen = 1024;
memset(databuf, 0x00, sizeof(databuf));
read_size = recvfrom(sd, databuf, datalen, 0,
(struct sockaddr*) &rcv_addr, &rcv_addr_size);
printf("The message from multicast ckient is: \"%s\"\n", databuf);
}
return 0;
}
client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
struct sockaddr_in localSock, rcv_addr;
struct ip_mreq group;
int sd;
int datalen;
char databuf[1024];
int main(int argc, char *argv[]) {
/* Create a datagram socket on which to receive. */
socklen_t rcv_addr_size = sizeof(struct sockaddr_in);
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0) {
perror("Opening datagram socket error");
exit(1);
}
else
printf("Opening datagram socket....OK.\n");
{
int reuse = 1;
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse,
sizeof(reuse)) < 0) {
perror("Setting SO_REUSEADDR error");
close(sd);
exit(1);
} else
printf("Setting SO_REUSEADDR...OK.\n");
}
memset((char*) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(4321);
localSock.sin_addr.s_addr = INADDR_ANY;
if (bind(sd, (struct sockaddr*) &localSock, sizeof(localSock))) {
perror("Binding datagram socket error");
close(sd);
exit(1);
} else
printf("Binding datagram socket...OK.\n");
group.imr_multiaddr.s_addr = inet_addr("226.1.1.1");
group.imr_interface.s_addr = INADDR_ANY;
if (setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &group,
sizeof(group)) < 0) {
perror("Adding multicast group error");
close(sd);
exit(1);
} else
printf("Adding multicast group...OK.\n");
int read_size;
while (1) {
datalen = 1024;
memset(databuf, 0x00, sizeof(databuf));
read_size = recvfrom(sd, databuf, datalen, 0,
(struct sockaddr*) &rcv_addr, &rcv_addr_size);
printf("The message from multicast server is: \"%s\"\n", databuf);
memset(databuf, 0x00, sizeof(databuf));
scanf("%s", databuf);
datalen = strlen(databuf) + 1;
if (sendto(sd, databuf, datalen, 0, (struct sockaddr*) &localSock,
sizeof(localSock)) < 0)
break;
}
return 0;
}
Your server is sending to the wrong address.
The server is using localSock as the destination address for sendto:
if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&localSock, sizeof(localSock)) < 0)
But you have that address set to 0:
localSock.sin_family = AF_INET;
localSock.sin_port = htons(4321);
localSock.sin_addr.s_addr = INADDR_ANY;
You want to instead use rcv_addr, which was populated as the source address from recvfrom. Using this address as the destination will send the response back where it came from:
if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&rcv_addr, sizeof(rcv_addr)) < 0)
Multicast connection is like broadcast communication, you send the packet to a forum of receivers, awaiting to read it, and they consume it (if it arrives). This normally means that you have to arrange for bidirectional connection in a way that allows all people skeaking in a room and selecting yourself the responses, as everybody is talking to everybody in a multicast channel. Imagine you are chatting in a IRC channel, and you have to arrange with somebody how to direct messages only to that person, but with the anarchy of anybody being able to respond to such messages in the way they want. You have always to think that what you say, you say to everybody susbscribed in that multicast channel, so normally you will receive several response packets, from which you will have to select...

getaddrinfo: Address family for nodename not supported in MacOS

I keep getting this error getaddrinfo failed: Undefined error: 0. I am trying to compile my code on MacOS using the command gcc mac-client-2.c -o client. The program is compiling successfully, but when I run the executable, the error above shows up. I searched google and SO, the closest thing I could find to the problem was this link Undefined reference to getaddrinfo But, this link talks about the issue for windows, not for MacOS.
I am pasting my code as it is below. Could anyone please help.
EDIT: Got a more descriptive error saying getaddrinfo: Address family for nodename not supported
// Client side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/udp.h> //Provides declarations for udp header
#include <netinet/ip.h> //Provides declarations for ip header
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netdb.h>
#include <errno.h>
#define PORT 12345
#define MAXLINE 1024
//standard checksum function
unsigned short csum(unsigned short *ptr, int nbytes)
{
register long sum;
unsigned short oddbyte;
register short answer;
sum = 0;
while (nbytes > 1)
{
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1)
{
oddbyte = 0;
*((u_char *)&oddbyte) = *(u_char *)ptr;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum = sum + (sum >> 16);
answer = (short)~sum;
return (answer);
}
// struct ip
// {
// unsigned char ihl;
// unsigned char version;
// unsigned char tos;
// unsigned short int tot_len;
// unsigned short int id;
// unsigned short int frag_off;
// unsigned char ttl;
// unsigned char protocol;
// unsigned short int check;
// unsigned int saddr;
// unsigned int daddr;
// };
//required for udp
struct pseudo_header
{
u_int32_t source_address;
u_int32_t dest_address;
u_int8_t placeholder;
u_int8_t protocol;
u_int16_t udp_length;
};
// Driver code
int main()
{
int errno;
int sockfd, raw_sock;
char buffer[MAXLINE];
int port;
char *hello = "Client Hello";
char *done = "Client Done";
char source_ip[32];
struct sockaddr_in servaddr;
struct sockaddr_in local_address;
int addr_size = sizeof(local_address);
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket creation failed");
exit(EXIT_FAILURE);
}
if ((raw_sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0) //PF_PACKET -- 0 can be replaced with IPPROTO_UDP (gives same outcome)
{
perror("Raw Socket creation failed");
exit(EXIT_FAILURE);
}
setuid(getuid());
//********** Part with getaddrinfo//*********
int stat;
struct addrinfo hints;
struct addrinfo *info, *ptr;
struct sockaddr_in *client_address;
char clientIPstr[16];
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; //put NULL in getaddrinfo
//AI_PASSIVE allows to assign address of local host
//No hardcoding needed
if ((stat = getaddrinfo(NULL, "0", &hints, &info) != 0))
{
perror("getaddrinfo failed");
exit(EXIT_FAILURE);
}
for (ptr = info; ptr != NULL; ptr = ptr->ai_next)
{
if (ptr->ai_family == AF_INET)
{
client_address = (struct sockaddr_in *)ptr->ai_addr;
inet_ntop(AF_INET, &(client_address->sin_addr), clientIPstr, sizeof(clientIPstr));
printf("%s\n", clientIPstr);
int x = bind(sockfd, ptr->ai_addr, ptr->ai_addrlen);
//int y = bind(raw_sock, ptr->ai_addr, ptr->ai_addrlen);
//printf("Bind Status: %d, %d\n", x, y);
break;
}
}
///************///************////*****************
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET; //IPv4
servaddr.sin_port = htons(PORT); //8080
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
int len, n;
//send hello
sendto(sockfd, (const char *)hello, strlen(hello),
0, (const struct sockaddr *)&servaddr,
sizeof(servaddr));
//fetch the port number and store in local address -- dont forget to convert using ntohs
getsockname(sockfd, (struct sockaddr *)&local_address, &addr_size);
port = ntohs(local_address.sin_port);
printf("My Port: %u\n", port);
//receive hello
bzero(buffer, MAXLINE);
recvfrom(sockfd, buffer, sizeof(buffer),
0, (struct sockaddr *)&servaddr,
&len);
printf("%s\n", buffer);
/* ---------------------Packet spoofing code starts here----------------------- */
printf("Creating spoofed packet\n");
char spoof_packet[4096];
char *data, *pseudogram;
int one = 1;
const int *val = &one;
memset(spoof_packet, 0, 4096);
//strcpy(clientIPstr, "127.0.0.1");
struct ip *iph = (struct ip *)spoof_packet;
struct udphdr *udph = (struct udphdr *)(spoof_packet + sizeof(struct ip));
struct pseudo_header psh;
struct sockaddr_in my_sockaddress;
my_sockaddress.sin_addr.s_addr = inet_addr(clientIPstr); //just set this to htonl(INADDR_ANY); instead of 127.0.0.1
//struct sockaddr_in sin;
data = spoof_packet + sizeof(struct ip) + sizeof(struct udphdr);
strcpy(data, "SPOOFED CLIENT DONE");
strcpy(source_ip, clientIPstr);
//IP Header
iph->ip_hl = 5;
iph->ip_v = 4;
iph->ip_tos = 0;
iph->ip_len = sizeof(struct ip) + sizeof(struct udphdr) + strlen(data);
iph->ip_id = htonl(54321); //Id of this packet
iph->ip_off = 0;
iph->ip_ttl = 255;
iph->ip_p = IPPROTO_UDP;
iph->ip_sum = 0; //Set to 0 before calculating checksum
iph->ip_src = my_sockaddress.sin_addr; //Spoof the source ip address
iph->ip_dst = servaddr.sin_addr; //value should be of type in_addr
iph->ip_sum = csum((unsigned short *)spoof_packet, iph->ip_len); //ip checksum
//UDP header
udph->uh_sport = local_address.sin_port;
udph->uh_dport = htons(PORT);
udph->uh_ulen = htons(8 + strlen(data)); //header size
udph->uh_sum = 0; //leave checksum 0 now, filled later by pseudo header
/* Stackoverflow - The IPv4 layer generates an IP header when sending a packet unless the IP_HDRINCL socket
option is enabled on the socket. When it is enabled, the packet must contain an IP header.
For receiving the IP header is always included in the packet.*/
if (setsockopt(raw_sock, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
{
perror("setsockopt() error");
exit(-1);
}
//UDP checksum using the pseudo header
psh.source_address = inet_addr(source_ip);
psh.dest_address = servaddr.sin_addr.s_addr;
psh.placeholder = 0;
psh.protocol = IPPROTO_UDP;
psh.udp_length = htons(sizeof(struct udphdr) + strlen(data));
int psize = sizeof(struct pseudo_header) + sizeof(struct udphdr) + strlen(data);
pseudogram = malloc(psize);
memcpy(pseudogram, (char *)&psh, sizeof(struct pseudo_header));
memcpy(pseudogram + sizeof(struct pseudo_header), udph, sizeof(struct udphdr) + strlen(data));
udph->uh_sum = csum((unsigned short *)pseudogram, psize);
printf("%s\n", spoof_packet);
printf("Sending spoofed packet.......");
int k;
//send spoofed Done
k = sendto(raw_sock, spoof_packet, iph->ip_len,
0, (const struct sockaddr *)&servaddr,
sizeof(servaddr));
if (k == -1)
{
printf("Error sending: %i\n", errno);
}
printf("%d\n", k);
fflush(stdout);
/*---------------------------------END------------------------------------------*/
//send Done
// sendto(sockfd, (const char *)done, strlen(done),
// 0, (const struct sockaddr *)&servaddr,
// sizeof(servaddr));
//receive done
bzero(buffer, MAXLINE);
recvfrom(sockfd, buffer, sizeof(buffer),
0, (struct sockaddr *)&servaddr,
&len);
printf("%s\n", buffer);
//close(sockfd);
return 0;
}
/* get ip and port number:
char myIP[16];
struct sockaddr_in local_address;
getsockname(sockfd, (struct sockaddr *)&local_address, &addr_size); //get socket info
inet_ntop(AF_INET, &local_address.sin_addr, myIP, sizeof(myIP)); // get IP info
int myPort = ntohs(local_address.sin_port); //get port info
printf("Local ip address: %s\n", myIP);
printf("Local port : %u\n", myPort);
*/
Your struct addrinfo hints; is uninitialized, and has junk in the members you did not explicitly write to. Change it to struct addrinfo hints = { 0 }; or put all the hints in designated initializers rather than assignments after creation of an uninitialized object.
So, I forgot to post back here. I had figured out the solution. Its basically the same as the above post. Just added the line memset(&hints,0,sizeof(hints)) and everything worked perfectly.

Building and send RAW datagrams

Hello I would like to make a programm which would work similarly to "SendIP a command-line tool to send arbitrary IP packets"
I have a programm to send "IPv4 + UDP". I try to validate my program by Wireshark but nothing is received and I don't know why.
I send it by command ./Project 192.168.1.15 21 192.168.1.15 8080 5
Here is my code: (In ipv4.h and udp.h I have ip and udp headers)
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include "ipv4.h"
#include "udp.h"
// Source IP, source port, target IP, target port from the command line arguments
int main(int argc, char *argv[])
{
if (argc != 6)
{
printf("- Invalid parameters!!!\n");
printf(
"- Usage %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n",
argv[0]);
exit(-1);
}
else {
int sd;
char buffer[PCKT_LEN];
struct ipheader *ip = (struct ipheader *) buffer;
struct udpheader *udp = (struct udpheader *) (buffer
+ sizeof(struct ipheader));
// Source and destination addresses: IP and port
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;
memset(buffer, 0, PCKT_LEN);
// Create a raw socket with UDP protocol
sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
if (sd < 0)
{
perror("socket() error");
// If something wrong just exit
exit(-1);
}
else
printf(
"socket() - Using SOCK_RAW socket and UDP protocol is OK.\n");
// The address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
// Port numbers
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));
// IP addresses
sin.sin_addr.s_addr = inet_addr(argv[1]);
din.sin_addr.s_addr = inet_addr(argv[3]);
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16; // Low delay
ip->iph_len = sizeof(struct ipheader) + sizeof(struct udpheader);
ip->iph_ident = htons(54321);
ip->iph_ttl = 64; // hops
ip->iph_protocol = 17; // UDP
ip->iph_sourceip = inet_addr(argv[1]);
// The destination IP address
ip->iph_destip = inet_addr(argv[3]);
// Fabricate the UDP header. Source port number, redundant
udp->udph_srcport = htons(atoi(argv[2]));
// Destination port number
udp->udph_destport = htons(atoi(argv[4]));
udp->udph_len = htons(sizeof(struct udpheader));
// Calculate the checksum for integrity
ip->iph_chksum = csum((unsigned short *) buffer,
sizeof(struct ipheader) + sizeof(struct udpheader));
if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
{
perror("setsockopt() error");
exit(-1);
}
else
printf("setsockopt() is OK.\n");
printf("Trying...\n");
printf("Using raw socket and UDP protocol\n");
printf("Using Source IP: %s port: %u, Target IP: %s port: %u.\n",
argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));
//printf("Interfejs=%d\n", *val);
int count;
int number = (atoi(argv[5]));
printf("Number=%d\n", number);
for (count = 1; count <= number; count++)
{
if (sendto(sd, buffer, ip->iph_len, 0, (struct sockaddr *) &sin,
sizeof(sin)) < 0)
{
perror("sendto() error");
exit(-1);
}
else
{
printf("Count #%u - sendto() is OK.\n", count);
sleep(2);
}
}
close(sd);
return 0;
}
}
Ok I fix it. The problem was with int one = 1; which specife number of interface. I changed to 0 and it works. What a stupid mistake :D

C socket programming: recv always fail

i'm trying to understand C socket programming for an university exam.
I made this simple example:
socket_server.c
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define SA struct sockaddr
#define MAX_MESS_LEN 16
int main(){
struct sockaddr_in my_addr, cl_addr;
int ret, len, sk, cn_sk;
char cl_ip[INET_ADDRSTRLEN + 1], msg[MAX_MESS_LEN + 1];
sk = socket(AF_INET, SOCK_STREAM, 0); //creo socket TCP/IPv4 listener
printf("socket created! :)\n");
memset(&my_addr, 0, sizeof(my_addr)); //azzero struttura my_addr
my_addr.sin_family = AF_INET; //famiglia protocolli IPv4
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); //in ascolto su qualsiasi interfaccia
my_addr.sin_port = htons(1234); //porta del socket
ret = bind(sk, (SA *) &my_addr, sizeof(my_addr)); //lego il socket alla struttura indirizzo
printf("socket binded! :)\n");
ret = listen(sk, 10); //mi pongo in ascolto sul socket con massimo 10 richieste pendenti
printf("socket listening (on any interface with port 1234)! :)\n");
len = sizeof(cl_addr);
printf("socket is going to wait for a request... zzzzZZZ\n");
cn_sk = accept(sk, (SA *) &cl_addr, &len); //creo il socket connected per la richiesta in cima alla lista
printf("socket accepted request! :D\n");
inet_ntop(AF_INET, &cl_addr.sin_addr, cl_ip, INET_ADDRSTRLEN); //converto indirizzo IPv4 cl_addr.sin_addr in stringa (cl_ip)
printf("IP client: %s\n", cl_ip);
ret = recv(sk, (void *) msg, MAX_MESS_LEN, MSG_WAITALL); //attendo la ricezione di tutti i caratteri della stringa inviata sul socket dal client
msg[MAX_MESS_LEN + 1] = '\0';
printf("received data (%d bytes): %s\n", ret, msg);
if(ret == -1 || ret < MAX_MESS_LEN)
printf("recv ERROR! :(\n");
close(sk); //chiudo il server
}
socket_client.c
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#define SA struct sockaddr
#define MSG_LEN 17
int main(){
struct sockaddr_in srv_addr;
int ret, sk;
char msg[MSG_LEN];
sk = socket(AF_INET, SOCK_STREAM, 0);
printf("Socket created! :)\n");
memset(&srv_addr, 0, sizeof(srv_addr));
srv_addr.sin_family = AF_INET;
srv_addr.sin_port = htons(1234);
ret = inet_pton(AF_INET, "192.168.1.132", &srv_addr.sin_addr);
printf("Trying to establish a connection with 192.168.1.132 on port 1234...");
ret = connect(sk, (SA *) &srv_addr, sizeof(srv_addr)); //faccio una richiesta sul socket
if(ret != -1) printf("Connection established! :D\n");
else printf(" connection error :(\n");
strcpy(msg, "something to send"); //scrivo messaggio in una stringa
printf("sending message: %s\n", msg);
ret = send(sk, (void *) msg, strlen(msg), 0); //invio il messaggio sul socket
if(ret == -1 || ret < strlen(msg))
printf("send ERROR! :(\n");
close(sk);
}
And compiled it with:
gcc socket_client.c -o socket_client
gcc socket_server.c -o socket_server
Maybe it's a stupid question but the recv function in server always fail, there is an example output:
Server:
socket created! :)
socket binded! :)
socket listening (on any interface with port 1234)! :)
socket is going to wait for a request... zzzzZZZ
socket accepted request! :D
IP client: 192.168.1.132
received data (-1 bytes): ����
recv ERROR! :(
Client:
Socket created! :)
Trying to establish a connection with 192.168.1.132 on port 1234...Connection established! :D
sending message: something to send
What's the problem? I don't get it! :( I followed step by step, my teacher's guide.
I'm running on arch linux 64 bit ;)
Thank you for response!
cn_sk = accept(sk, (SA *) &cl_addr, &len); //creo il socket connected per la richiesta in cima alla lista
...
ret = recv(sk, (void *) msg, MAX_MESS_LEN, MSG_WAITALL); //at
You don't recv on the connected socket cn_sk to the client, but instead on the listener socket sk. If you would check the errno you would probably see ENOTCONN.

Tracing a client-server transaction - sockets in c

I am very new to socket programming, I want to simulate a client-server transaction. So for my client sent packet, I declare a sock = socket(AF_INET, SOCK_STREAM, 0), a SOCKADDR_IN sin, I bind them through bind(sock, (SOCKADDR*) &sin, sizeof(sin)), then, after declaring a classic struct ip header, and hydrating a allocating some memory to struct iphdr * ip, I finally send the packet via ip
sent_packet = sendto(sock, packet, sizeof(struct iphdr) + sizeof(struct tcphdr),
0, (struct sockaddr *) sin, sizeof(struct sockaddr));//sent_packet is an int, I use also a TCP header struct, packet is the pointer that stores the ip and tcp data
This seems to work. But now, I want to trace the sent packet, so I use a server side file to declare again a sock, I declare a SOCKADDR_IN client_sin I accept the connection of the client via accept(sock, (SOCKADDR*)&client_sin, &recsize);, but it seems that my packet is not received ? I use for that recv(sock, buffer, 32, 0) != SOCKET_ERROR to catch the packets, (of course I launched the server program before the client one). Am going completely wrong ?
Edit on the client side (to shorten, I didn't mention the included libraries, the `struct` `iphdr`, `tcphdr`, the `in_chksum function`, as well I didn't hydrate the tcp header, for now I just want to test)
#define PORT 23
int sendmeifyoucan(SOCKET sock, SOCKADDR_IN * sin , int size ){
struct iphdr * ip = (struct iphdr *)malloc(sizeof(struct iphdr *));
struct tcphdr * tcp;
char * packet;
int psize=0, status = 1;
printf("%d I am lost in the web ",status);
packet = malloc(sizeof(struct iphdr)+ sizeof(struct tcphdr));
memset(packet, 0, sizeof(struct iphdr) + sizeof(struct tcphdr));
sin->sin_addr.s_addr = inet_addr("127.0.0.1");
ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + psize);
ip->ihl = 5;
ip->version = 4;
ip->ttl = 255;
ip->tos = 0;
ip->frag_off = 0;
ip->protocol = IPPROTO_ICMP;
ip->saddr = sin->sin_addr.s_addr;
ip->daddr = sin->sin_addr.s_addr;
ip->check = in_chksum((u_short *)ip, sizeof(struct iphdr));
status = sendto(sock, packet, sizeof(struct iphdr) + sizeof(struct tcphdr),
0, (struct sockaddr *) sin, sizeof(struct sockaddr));
free(packet);
return 0;
}
int main(void)
{
int erreur = 0;
SOCKADDR_IN sin;
SOCKET sock;
SOCKADDR_IN csin;
SOCKET csock;
int sock_err;
if(!erreur)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock != INVALID_SOCKET)
{
printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
int size = 0;
/* Configuration */
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
/* Listage du port */
sendmeifyoucan(sock, &sin,size);
printf("Fermeture de la socket client\n");
closesocket(csock);
printf("Fermeture de la socket serveur\n");
closesocket(sock);
printf("Fermeture du serveur terminée\n");
}
else
perror("socket");
}
return EXIT_SUCCESS;
}
Edit on the server side
#define PORT 23
int main(void)
{
int erreur = 0;
SOCKET sock;
SOCKADDR_IN sin;
socklen_t recsize = sizeof(sin);
SOCKADDR_IN csin;
char buffer[32] = "";
int sock_err;
if(!erreur)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock != INVALID_SOCKET)
{
printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
/* Configuration */
csin.sin_addr.s_addr = inet_addr("127.0.0.1");
csin.sin_family = AF_INET;
csin.sin_port = htons(PORT);
sock_err = bind(sock, (SOCKADDR*) &csin, sizeof(csin));
if(sock_err != SOCKET_ERROR)
{
sock_err = listen(sock, 5);
printf("Listage du port %d...\n", PORT);
}
if(sock_err != SOCKET_ERROR)
{
/* Attente pendant laquelle le client se connecte */
printf("Patientez pendant que le client se connecte sur le port %d...\n", PORT);
sock = accept(sock, (SOCKADDR*)&sin, &recsize);
}
if(recv(sock, buffer, 32, 0) != SOCKET_ERROR)
{
printf("Recu : %s\n", buffer);
}
else
{
printf("Impossible de se connecter\n");
}
closesocket(sock);
}
else
perror("socket");
}
return EXIT_SUCCESS;
}
You can't use sendto with a SOCK_STREAM socket. Use connect and either send or write instead.
Also, you usually don't use struct iphdr and struct tcphdr in normal socket programming, those are only used with raw ip packets (which sockets aren't).

Resources