I'm new to c++ and need help.
I use an UDP server to receive structure however i have problem to read it , the client send a structure I call : ChannAccessReq so the structure is send and the server receive it with RECVFROM and I use a general structure by reading the header (H1) of the struct only and then i do a read when a condition is fullfill with a more precise structure (temp2) for the buffer. However the client need to send the message twice , the first time it goes until recvfrom and the second it reach read() (i think) I tried all the day and wonder if its the size of the buffer ?
I think the most sensitive part is in the server with the recvfrom() who have a struct different from the read() just after..
I hope it's clear!
here is the server :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
#include <iostream>
void DieWithError(char *err) {
perror(err);
exit(1);
}
typedef struct IntMsgHeaderType {
uint8_t code ; // Code message7
uint8_t bourrage ; // Octet de bourrage
uint16_t ParamLength; // Longueur eventuel données complémentaires
} HeaderInt;
typedef struct TextMessage //TESTTESTTEST
{
HeaderInt H; // Code message7
};
int main(int argc, char *argv[])
{
int sock; /* Socket */
struct sockaddr_in echoServAddr; /* Local address */
struct sockaddr_in echoClntAddr; /* Client address */
unsigned int cliAddrLen; /* Length of incoming message */
unsigned short echoServPort; /* Server port */
int recvMsgSize; /* Size of received message */
struct TextMessage * temp = (TextMessage *)malloc(sizeof(struct TextMessage));
HeaderInt *H1 =(HeaderInt *)malloc(104+sizeof(HeaderInt));
ChanAccesReq *temp2=(ChanAccesReq *)malloc(sizeof(ChanAccesReq));
if (!argv[1]) {
fprintf(stderr,"no port number provided");
exit(1);
}
echoServPort = atoi(argv[1]); /* First arg: local port */
/* Create socket for sending/receiving datagrams */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct local address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
echoServAddr.sin_port = htons(echoServPort); /* Local port */
/* Bind to the local address */
if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("bind() failed");
for (;;) /* Run forever */
{
cliAddrLen = sizeof(echoClntAddr);
int nbrOctet;
if (recvfrom(sock, H1, sizeof(*H1), 0,(struct sockaddr *) &echoClntAddr, &cliAddrLen)>0 && H1->code==1){
//read(sock,H1,sizeof(*H1));
std::cout<<"taille nbrOctet : "<<nbrOctet<<'\n';
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
read(sock, temp2, sizeof(*temp2));
//read(sock,temp2,sizeof(*temp2))>0;
std::cout<<unsigned(temp2->P.linkAddr)<<'\n';
};
}
close(sock);
return 0;
}
and here the client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
void DieWithError(char *err) {
perror(err);
exit(1);
}
typedef struct {
char transMode ;
uint8_t linkAddr;
} ChanAccessReqParam;
typedef struct {
HeaderInt H;
ChanAccessReqParam P;
} ChanAccesReq ;
int main(int argc, char *argv[])
{
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* Echo server address */
struct sockaddr_in fromAddr; /* Source address of echo */
unsigned short echoServPort; /* Echo server port */
unsigned int fromSize; /* In-out of address size for recvfrom() */
char *servIP; /* IP address of server */
int structLen; /* Length of string to echo */
int respStringLen; /* Length of received response */
if (!argv[1]) {
fprintf(stderr,"No server IP sepcified at arg 1\n");
exit(1);
}
else if (!argv[2]) {
fprintf(stderr,"No port Number Sepcified at arg 2\n");
exit(2);
}
ChanAccesReq test { 1 ,1,0,'c',15};
servIP = argv[1]; /* First arg: server IP address (dotted quad) */
echoServPort = atoi(argv[2]); /* Use given port, if any */
/* Create a datagram/UDP socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet addr family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */
int tempint = 0;
tempint = sendto(sock, (ChanAccesInd*)&test, 10+(sizeof(test)), 0, (struct sockaddr *)
&echoServAddr, sizeof(echoServAddr));
if (tempint == -1 ) {
printf("Sent struct size: %d\n", tempint);
DieWithError("sendto() sent a different number of bytes than expected\n");
}
close(sock);
exit(0);
}
Thank you for your help
you can use a flag on recvfrom like "PEEK" see the modified code here :
recvfrom(sock, HeaderStruct, sizeof(*HeaderStruct), MSG_PEEK,(struct sockaddr *) &echoClntAddr, &cliAddrLen);
and the full code here
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
#include <iostream>
void GesCanSrvRecvMsg(){
int sock; // Socket
struct sockaddr_in echoServAddr; // Adresse local
struct sockaddr_in echoClntAddr; // Adresse Client
unsigned int cliAddrLen; // Longeur des messages entrant
unsigned short echoServPort; // Port Serveur
unsigned recvMsgSize; // Taille message reçu
//Creation allocation memoire necessaire pour recevoir les structures
HeaderInt *HeaderStruct=(HeaderInt *)malloc(sizeof(HeaderInt));
ChanAccesReq *ChanReqStruct=(ChanAccesReq *)malloc(sizeof(ChanReqStruct));
TransTimeReq *TransTReqStruct=(TransTimeReq *)malloc(sizeof(TransTReqStruct));
TransCancelReq *TransCReqStruct=(TransCancelReq *)malloc(sizeof(TransCReqStruct));
//Port definie a 13000
echoServPort = atoi("13000"); //Premier argument port local
//Creation socket
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
Error("socket() failed");
//Construct local address structure
memset(&echoServAddr, 0, sizeof(echoServAddr));
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
echoServAddr.sin_port = htons(echoServPort);
//Bind a ladresse
if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
Error("bind() failed");
while(1) //Boucle infinie
{
cliAddrLen = sizeof(echoClntAddr);
HeaderStruct->code=0;
/*Attente des messages en ne regarde que l'entete Header
Flag -> MSG_PEEK pour eviter un double envoie du client*/
recvfrom(sock, HeaderStruct, sizeof(*HeaderStruct), MSG_PEEK,(struct sockaddr *) &echoClntAddr, &cliAddrLen);
std::cout<<"coucou"<<'\n';
char* subscIPAddr=inet_ntoa(echoClntAddr.sin_addr); // adresse iP Client
if (unsigned(HeaderStruct->code)==ChanAccessReqc){ //Si code == ChanAccessReqC (1)
recv(sock,ChanReqStruct,sizeof(*ChanReqStruct),0);
CSMAChnAccessLstReq.push_back(*ChanReqStruct); //Placement dans liste partagée avec GesCanSlot
}
else if (unsigned(HeaderStruct->code==TransTimeReqc)){ //Si code == TransTimeReqc (3)
recv(sock,TransTReqStruct,sizeof(*TransTReqStruct),0);
CSMATimeTransmLstReq.push_back(*TransTReqStruct);
}
else if (unsigned(HeaderStruct->code==TransCancelReqc)){ //Si code == TransCancelReqc (3)
recv(sock,TransCReqStruct,sizeof(*TransCReqStruct),0);
TransacCancelLst.push_back(*TransCReqStruct);
}
else {
Error("Error");
}
}
close(sock);
};
int main(int argc, char *argv[])
{
GesCanSrvRecvMsg();
return 0;
}
Related
I am trying to implement the following code for a simple FTP between a client and a server. The problem is, when the server sends the file to the client, the file is empty. I'm not sure what the problem is. I'm assuming the problem lies when the server sends the file. Below is the code.
/*Server Code*/
#ifndef unix
#define WIN32
#include <windows.h>
#include <winsock.h>
#else
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <netdb.h>
#endif
#include <stdio.h>
#include <string.h>
#define PROTOPORT 5193 /* default protocol port number */
#define QLEN 6 /* size of request queue */
int visits = 0; /* counts client connections */
main(argc, argv)
int argc;
char *argv[];
{
struct hostent *ptrh; /* pointer to a host table entry */
struct protoent *ptrp; /* pointer to a protocol table entry */
struct sockaddr_in sad; /* structure to hold server.s address */
struct sockaddr_in cad; /* structure to hold client.s address */
int sd, sd2; /* socket descriptors */
int port; /* protocol port number */
int alen; /* length of address */
char buf_recv[1000],buf_send[1000]; /* buffer for string the server sends */
char file_buffer[10000],f_buffer[1000];
int n;
FILE *fp;
#ifdef WIN32
WSADATA wsaData;
WSAStartup(0x0101, &wsaData);
#endif
memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address */
if (argc > 1) { /* if argument specified */
port = atoi(argv[1]);
} else {
port = PROTOPORT; /* use default port number */
}
if (port > 0) /* test for illegal value */
sad.sin_port = htons((u_short)port);
else { /* print error message and exit */
fprintf(stderr,"bad port number %s\n",argv[1]);
exit(1);
}
/* Map TCP transport protocol name to protocol number */
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Create a socket */
sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (sd < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Bind a local address to the socket */
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"bind failed\n");
exit(1);
}
/* Specify size of request queue */
if (listen(sd, QLEN) < 0) {
fprintf(stderr,"listen failed\n");
exit(1);
}
alen = sizeof(cad);
if ( (sd2=accept(sd, (struct sockaddr *)&cad, &alen)) < 0) {
fprintf(stderr, "accept failed\n");
exit(1);
}
sprintf(buf_send,"Please enter the file name: ");
send(sd2,buf_send,strlen(buf_send),0);
n=recv(sd2,buf_recv,1000,0);
buf_recv[n]='\0';
printf("%s\n",buf_recv);
fflush(stdout);
if((fp = fopen(buf_recv,"r"))==NULL)
{
sprintf(buf_send,"File could not be found!!!");
exit(0);
} else
sprintf(buf_send,"File found!!!\n");
send(sd2,buf_send,strlen(buf_send),0);
n=recv(sd2,buf_recv,1000,0);
printf("%s",buf_recv);
fflush(stdout);
while(!feof(fp)) {
fgets(f_buffer,1000,fp);
if (feof(fp))
break;
strcat(file_buffer,f_buffer);
}
fclose(fp);
send(sd2,file_buffer,strlen(file_buffer),0);
closesocket(sd2);
exit(0);
}
The Client Code:
/*Client Code*/
#ifndef unix
#define WIN32
#include <windows.h>
#include <winsock.h>
#else
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
#include <stdio.h>
#include <string.h>
#define PROTOPORT 5193 /* default protocol port number */
extern int errno;
char localhost[] = "localhost"; /* default host name */
main(argc, argv)
int argc;
char *argv[];
{
struct hostent *ptrh; /* pointer to a host table entry */
struct protoent *ptrp; /* pointer to a protocol table entry */
struct sockaddr_in sad; /* structure to hold an IP address */
int sd; /* socket descriptor */
int port; /* protocol port number */
char *host; /* pointer to host name */
int n; /* number of characters read */
char buf_recv[1000],buf_send[100]; /* buffer for data from the server */
char *filename;
char file_buffer[10000];
FILE *fp;
#ifdef WIN32
WSADATA wsaData;
WSAStartup(0x0101, &wsaData);
#endif
memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
if (argc > 2) { /* if protocol port specified */
port = atoi(argv[2]); /* convert to binary */
} else {
port = PROTOPORT; /* use default port number */
}
if (port > 0) /* test for legal value */
sad.sin_port = htons((u_short)port);
else { /* print error message and exit */
fprintf(stderr,"bad port number %s\n",argv[2]);
exit(1);
}
/* Check host argument and assign host name. */
if (argc > 1) {
host = argv[1]; /* if host argument specified */
} else {
host = localhost;
}
/* Convert host name to equivalent IP address and copy to sad. */
ptrh = gethostbyname(host);
if ( ((char *)ptrh) == NULL ) {
fprintf(stderr,"invalid host: %s\n", host);
exit(1);
}
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
/* Map TCP transport protocol name to protocol number. */
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Create a socket. */
sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (sd < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Connect the socket to the specified server. */
if (connect(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"connect failed\n");
exit(1);
}
n = recv(sd, buf_recv, sizeof(buf_recv), 0);
buf_recv[n]='\0';
printf("%s",buf_recv);
scanf("%s",buf_send);
send(sd,buf_send,strlen(buf_send),0);
n = recv(sd, buf_recv, sizeof(buf_recv), 0);
buf_recv[n]='\0';
printf("%s",buf_recv);
fflush(stdout);
sprintf(buf_send,"Client acknowledges, Sending file now.\n");
send(sd,buf_send, strlen(buf_send),0);
n=recv(sd, file_buffer, sizeof(file_buffer), 0);
file_buffer[n]='\0';
fflush(stdout);
fp = fopen("transferredFile.TXT","w");
fputs(file_buffer,fp);
fclose(fp);
closesocket(sd);
exit(0);
}
Is the problem coming from the server sending or is it the client receiving? Thanks!
Server: 'strcat(file_buffer,f_buffer);' - concat to uninitialized array.
Server and Client: assumptions that data contains no nulls, ie. system cannnot transfer binary data, only text.
Server and Client - assumptions that all the file data will fit in one line.
Server and Client - assumptions that TCP can transfer messages larger than one byte.
Probably other bugs associated with TCP streaming and C null-terminated strings.
Please help! This is due in a few hours and I've had no luck w/ online searches
CODE:
/*
Description:
The client should first send a datagram to the LocationServer.
The LocationServer will be listening on port number 23510 of the host c-lnx001.engr.uiowa.edu.
The message contained in this datagram should be the specified UserID (no null characters, blanks, line-feeds, or other extraneous characters).
The LocationServer will respond with a datagram containing the following information:
[WeatherServer hostname] [WeatherServer port #]
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h> /* for fprintf */
#include <string.h> /* for memcpy */
#include <strings.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#define SIZE 2048
int main(){
struct hostent *hp; /* host information */
struct sockaddr_in servaddr; /* server address */
char *my_message = "laura\0";/*USERID as message to server*/
char *buf_addr;
char *host = "c-lnx001.engr.uiowa.edu\0";
int port = 23510;
int fd;
/* fill in the server's address and data */
//memset((char*)&servaddr, 0, sizeof(servaddr)); ?
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(23510);
/* look up the address of the server given its name */
hp = gethostbyname("c-lnx001.engr.uiowa.edu");
if (!hp) {
fprintf(stderr, "could not obtain address of %s\n", host);
return 0;
}
/* put the host's address into the server address structure */
// DOESN't WORK: memcpy((void *)&servaddr.sin_addr, hp->h_addr_list[0], hp->h_length);
bcopy(hp->h_addr,(char*)&servaddr.sin_addr,hp->h_length);
if((fd = socket(AF_INET,SOCK_DGRAM, 0))<0)
{
exit(2);
}
/* send a message to the server */
if (sendto(fd, my_message, strlen(my_message), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("sendto failed");
return 0;
}
int addrlen = sizeof(servaddr);
recvfrom(fd,buf_addr,SIZE,0,(struct sockaddr*)&servaddr,&addrlen);
printf("%s\n", buf_addr);
}
I think your problem is that you're not resetting the serveraddr
Here's a working copy
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define IP_ADDRESS "127.0.0.1"
#define SERVER_PORT 5060
int main (int argc, char *argv[])
{
int recBytes, clientSocket=socket(AF_INET, SOCK_DGRAM, 0);
char buf[80], msg[]="greeting to server";
const int msgLen = sizeof(msg);
struct sockaddr_in serverAddr;
socklen_t reSize;
memset(&serverAddr, sizeof(struct sockaddr_in), 0);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVER_PORT);
inet_aton(IP_ADDRESS, &serverAddr.sin_addr);
if(sendto(clientSocket, msg, sizeof(msg), 0, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) != (sizeof(msg)))
{
perror("sendto");
return -1;
}
reSize = sizeof(struct sockaddr);
if((recBytes = recvfrom(clientSocket, buf, sizeof(buf)-1, 0, (struct sockaddr*)&serverAddr, &reSize)) == -1)
{
perror("recvfrom");
return -1;
}
buf[recBytes]='\0';
printf("%s\n", buf);
return 0;
}
How would I go about making this udpclient asynchronous using pthreads? I want to make sure UDP datagram won't be lost and also don't want the client program to wait forever and not be able to send any more messages
/*udpclient.c program */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN
#include <winsock.h>
#include <windows.h>
#endif
#ifndef WIN
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif
/* Here are some details of the sockaddr_in structure and the sockaddr structure
These declarations are copied from winsock.h
struct in_addr { this struct holds a 32 bit IP address
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
#define s_addr S_un.S_addr
struct sockaddr_in { notice this structure is 16 bytes long
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct sockaddr { this generic address structure is 16 bytes long, too!
u_short sa_family;
char sa_data[14];
};
*/
/* we have to send on the same port the server is listening on */
#define PORT 20009
/* simple upd client */
int main()
{
#ifdef WIN
SOCKET sock;
#else
int sock;
#endif
int size;
int nbytes, flags;
int i;
char * cp;
#ifdef WIN
WSADATA wsaData;
int nCode;
#endif
char buffer[100];
char str_addr[20]; /* holds the chars of an IP address */
struct sockaddr_in target_pc, me;
/* magic call to initialize the network I/O code - only Microsoft requires this */
#ifdef WIN
if((nCode = WSAStartup(MAKEWORD(1,1), &wsaData)) != 0){
printf("Opps! WSA error %d\n",nCode);
return -1;
}
#endif
/* create a socket to send on */
sock = socket(PF_INET,SOCK_DGRAM,0);
if(sock < 0) {
printf("socket error = %d\n", sock);
return -1;
}
/* we fill in the address family and port, but we do not know the destination IP address yet */
target_pc.sin_family = PF_INET;
target_pc.sin_port = htons(PORT);
/* fill in my address and port */
me.sin_family = PF_INET;
me.sin_port = htons(0);
me.sin_addr.s_addr = htonl(INADDR_ANY);
i = bind(sock, (struct sockaddr *) &me, sizeof(me));
if( i < 0) {
printf("bind result: %d\n", i);
return -1;
}
nbytes = 99;
while(1){
printf("Enter the target IP address: ");
cp = fgets(str_addr,19,stdin);
/* remove the \n */
str_addr[strlen(str_addr)-1] = '\0';
/* the inet_addr function converts a string form of IP address to a 32 binary integer */
target_pc.sin_addr.s_addr = inet_addr(&str_addr[0]);
printf("Enter your message: ");
cp = fgets(buffer,99,stdin);
/* get the string length so we send exactly this many characters */
nbytes = strlen(buffer);
flags = 0;
size = sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,sizeof(target_pc));
printf("msg size = %d size = %d\n", nbytes, size);
//added
int addrlen = sizeof(target_pc);
size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&target_pc,&addrlen);
if((size > 0) && (size < 99)){
buffer[size] = '\0'; //add the null byte so buffer now holds a string
i = puts((char *) buffer); // write this string to the display
}
}
#ifdef WIN
system("PAUSE");
#endif
return 0;
}
/udpserver.c program/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#ifdef WIN
#include <winsock.h>
#include <windows.h>
#endif
#ifndef WIN
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif
#define PORT 20009
/* simple upd server
this program receives short messages (<99 characters) from any IP address
and writes them to the display
be sure to use the linker line option "-l wsock32"
*/
int main()
{
/* first define a socket
a socket is an I/O port like a file descriptor
*/
#ifdef WIN
SOCKET sock; /* SOCKET is a typedef for a structure */
#else
int sock;
#endif
int size;
int nbytes, flags;
#ifdef WIN
int addrlen;
#else
socklen_t addrlen;
#endif
int i;
/* char loopback[20]="127.0.0.1"; */
#ifdef WIN
WSADATA wsaData; /* This is struct holds Windows required data */
int nCode;
#endif
char buffer[100];
struct sockaddr_in server; /* this holds my IP address and port info */
struct sockaddr_in from; /* this holds the same info for the sender of the packet
I received */
/* the call to WSAStartup is Windows magic */
#ifdef WIN
if((nCode = WSAStartup(MAKEWORD(1,1), &wsaData)) != 0){
printf("Opps! WSA error %d\n",nCode);
exit;
}
#endif
/* create a socket called sock. It is a datagram socket */
sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock < 0){
printf("socket error = %d\n", sock);
return -1;
}
server.sin_family = AF_INET; /* initialize the server address family */
server.sin_addr.s_addr = htonl(INADDR_ANY); /* notice this struct within a struct */
/* printf("%x\n",server.sin_addr.s_addr); */
server.sin_port = htons(PORT);
/* associate the socket with the address structure - this is called binding */
i = bind(sock, (struct sockaddr *) &server, sizeof(server));
if( i < 0) {
printf("bind result: %d\n", i);
return -1;
} else
printf("Simple UDP server is ready!\n\n");
nbytes = 99; /* receive packets up to 99 bytes long */
flags = 0; /* must be zero or this will not work! */
while(1){
/* the recvfrom function is a read and the arguments are:
sock - the socket we are reading
buffer - array into which to read the data
nbytes - read up to this many bytes
flags - used for special purposes - not needed here
from - sockaddr struct to hold the IP address and port of the sender of the packet
addrlen - the size of the sockaddr struct written by this function
*/
addrlen = sizeof(from);
size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&from, &addrlen);
if((size > 0) && (size < 99)){
buffer[size] = '\0'; /* add the null byte so buffer now holds a string */
i = puts((char *) buffer); /* write this string to the display */
}
//echo message back to client
if(sock < 0) {//
printf("socket error = %d\n", sock);//
return -1;//
}//
sendto(sock, buffer, nbytes, flags, (struct sockaddr *)&from,addrlen); //
}
#ifdef WIN
system("PAUSE");
#endif
return 0;
}
We could create two threads: one for the sendto (that waits for the user input) and the other for recvfrom(). Next, we can have the recvrom() use Pthread condvar (by calling pthread_cond_wait() on a condvar and a Pthread mutex) and wait. When the user provides an input, we can sendto (which is not really blocking) and then call pthread_cond_signal() to wake up the other thread.
You could certainly simply this, if you wanted. If your application permits, you could completely skip the pthread_cond_wait() since recvfrom() is anyways a blocking call. So, this way, recvfrom() would block but then it would go out of sync with the send calls. The other option is to use the main() thread for the sendto() thread -- in that case, you would just need one additional thread for the recv calls.
I have the following server code
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#define HELLO_PORT 12345
#define HELLO_GROUP "255.0.0.37"
main(int argc, char *argv[])
{
struct sockaddr_in addr;
struct sockaddr_in client,server;
int s,n;
char index;
int f;
char b1[100];
int fd, cnt,i=0;;
struct ip_mreq mreq;
//char *message="Hello, World!";
char *message=NULL;
/* create what looks like an ordinary UDP socket */
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0)
{
perror("socket");
exit(1);
}
s=socket(AF_INET,SOCK_DGRAM,0);
server.sin_family=AF_INET;
server.sin_port=2000;
server.sin_addr.s_addr=inet_addr("10.42.0.47");
bind(s,(struct sockaddr *)&server,sizeof(server));
printf("\nServer ready,waiting for client....\n");
n=sizeof(client);
/* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(HELLO_GROUP);
addr.sin_port=htons(HELLO_PORT);
/* now just sendto() our destination! */
while (1)
{
recvfrom(s,b1,sizeof(b1),0,(struct sockaddr *) &client,&n);
printf("client : %s\n",b1);
//sleep(5);
index=b1[0];
f=b1[0];
//printf("b1[1] is %c\n",index);
//printf("b1[0] is %c\n",f);
f=32;
b1[0]=f;
//printf("new b1[0] is %c\n",b1[0]);
//printf("%s\n",b1);
if(index!='C')
{
if (sendto(fd,b1,sizeof(b1),0,(struct sockaddr *) &addr,sizeof(addr)) < 0)
{
perror("sendto");
exit(1);
}
//i++;
/*if(i>=4)
{
i=0;
}*/
sleep(1);
}
}
}
And the following client code which runs on a different system
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdio.h>
#include <mysql.h>
#define HELLO_PORT 12345
#define HELLO_GROUP "225.0.0.37"
#define MSGBUFSIZE 1024
main(int argc, char *argv[])
{
MYSQL mysql;
MYSQL_ROW row;
MYSQL_RES *result;
unsigned int num_fields;
unsigned int i;
mysql_init(&mysql);
struct sockaddr_in server;
int s,n;
char b1[100],b2[100],a[100];
char re[100]={0};
char g=" ";
printf("%c\n",re);
strcpy(b2,"1");
char message[20],ch='n';
struct sockaddr_in addr;
int fd, nbytes,addrlen,j=0;
struct ip_mreq mreq;
char msgbuf[MSGBUFSIZE];
u_int yes=1; /*** MODIFICATION TO ORIGINAL */
/* create what looks like an ordinary UDP socket */
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0)
{
perror("socket");
exit(1);
}
s=socket(AF_INET,SOCK_DGRAM,0);
server.sin_family=AF_INET;
server.sin_port=2000;
server.sin_addr.s_addr=inet_addr("10.42.0.1");
printf("\nClient ready....\n");
n=sizeof(server);
if (!mysql_real_connect(&mysql,"localhost","root","nidhi","project",0,NULL,0))
{
fprintf(stderr, "Failed to connect to database: Error: %s\n",
mysql_error(&mysql));
}
/**** MODIFICATION TO ORIGINAL */
/* allow multiple sockets to use the same PORT number */
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0)
{
perror("Reusing ADDR failed");
exit(1);
}
/*** END OF MODIFICATION TO ORIGINAL */
/* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
addr.sin_port=htons(HELLO_PORT);
/* bind to receive address */
if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0)
{
perror("bind");
exit(1);
}
/* use setsockopt() to request that the kernel join a multicast group */
mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
mreq.imr_interface.s_addr=htonl(INADDR_ANY);
if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0)
{
perror("setsockopt");
exit(1);
}
/* now just enter a read-print loop */
while (1)
{
/*if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,(struct sockaddr *) &addr,&addrlen)) < 0)
{
perror("recvfrom");
exit(1);
}
printf("the server says: %s\n",msgbuf);*/
printf("would you like to send?(y/n)\n");
scanf("%c",&ch);
fflush(stdin);
if(ch=='y')
{
printf("\nClient:");
gets(a);
printf("%c\n",a);
strcat(b2,a);
printf("%s\n",b2);
sendto(s,b2,sizeof(b2),0,(struct sockaddr *) &server,n);
b2[100]=NULL;
strcpy(b2,"1");
}
addrlen=sizeof(addr);
if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,(struct sockaddr *) &addr,&addrlen)) < 0)
{
perror("recvfrom");
exit(1);
}
printf("the server says: %s\n",msgbuf);
if(mysql_query(&mysql,msgbuf));
else
{
strcpy(re,"Client 1: ");
sendto(s,re,sizeof(re),0,(struct sockaddr *) &server,n);
//printf("inside else case\n");
result=mysql_store_result(&mysql);
//printf("\n after getting the result...\n");
num_fields = mysql_num_fields(result);
//printf("\n after getting numfields...\n");
while ((row = mysql_fetch_row(result)))
{
unsigned long *lengths;
//printf("\n inside while....\n");
lengths = mysql_fetch_lengths(result);
for(i = 0; i < num_fields; i++)
{
printf("[%.*s] \t", (int) lengths[i], row[i] ? row[i] : "NULL");
strcat(re,row[i]);
j++;
//printf("%d\n",j);
if(j==4)
{
//printf("the result is .....%s\n",re);
sendto(s,re,sizeof(re),0,(struct sockaddr *) &server,n);
memset(re,0,100);
strcpy(re,"Client 1: ");
j=0;
}
}
printf("\n");
}
}
}
}
I created an adhoc network and it assigned two ip address to the server and the client.
10.42.0.1/24 to the server and 10.42.0.47/24 to client
however the unicast operation from the client to the server is not functioning correctly neither is the multicast from the server to client.
secondly how do i determine whether both the programs are part of the same multicast group. The error on the client is either
setsockopt:invalid argument
or
setsockopt:no such device
Any help on the same is greatly appreciated..!!
There are a lot of potential bugs in your code:
Server:
1.You are not checking if the 's' socket was successfully created. However, your example will work without it since there is enough memory for socket creation.
2.You are not checking the return code from bind(), maybe you can't bind the socket to the port and that's why you get 'invalid argument' error
3.You are not checking the return code from recvfrom() ....
4.The IP 255.0.0.37 is reserved for future use, I am not sure it is valid, why not use a valid ip range?
5.For multicasting you have to use ip addresses in range: 224.0.0.0/4, not 10.0.0.0/8 since it is reserved for local networks.
And regarding the client, you should first make working udp protocol code, and then add mysql to it. You also have to tell us at which line you have the error, otherwise it is difficult to analyse the problem.
soc = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); in client side, when run, get == -1 error
if accept function can only use with UDP and TCP higher protocol, how to accept multiple client with layer 2 communication?
where can find the code of accept function, i would like to rewrite it for layer 2.
Updated :
After tried soc = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
also == -1 , get this error
server side and client side both are the same computer, local one
strange is that running server side, it do not have this error, but running client program got error
//#include "stdafx.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <netinet/ether.h>
//#include "sock.h"
#define MAX_MESSAGE 21000
#define FD_NUM 5
#define tcp_port 5009
//#pragma comment(lib, "ws2_32.lib")
//#include <winsock2.h>
char host_ip[16] = "127.0.0.1";
void task()
{
struct sockaddr_in local;
int opt;
int soc;
//soc = socket(AF_INET,SOCK_STREAM,0);
soc = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (soc==-1) {
printf("socket error\n");
}
// determine ethernet number
/*
struct ifreq ifr;
size_t if_name_len=strlen(if_name);
if (if_name_len<sizeof(ifr.ifr_name)) {
memcpy(ifr.ifr_name,if_name,if_name_len);
ifr.ifr_name[if_name_len]=0;
} else {
printf("interface name is too long");
}
if (ioctl(fd,SIOCGIFINDEX,&ifr)==-1) {
printf("determine ethernet number error\n");
}
int ifindex=ifr.ifr_ifindex;
*/
// mac address
/*target address*/
struct sockaddr_ll socket_address;
/*buffer for ethernet frame*/
void* buffer = (void*)malloc(ETH_FRAME_LEN);
/*pointer to ethenet header*/
unsigned char* etherhead = (unsigned char*)buffer;
/*userdata in ethernet frame*/
unsigned char* data = (unsigned char*)buffer + 14;
/*another pointer to ethernet header*/
struct ethhdr *eh = (struct ethhdr *)etherhead;
int send_result = 0;
/*our MAC address*/
//10:78:d2:ad:90:cb
//0x10,0x78,0xD2,0xAD,0x90,0xCB
unsigned char src_mac[6] = {0x10,0x78,0xD2,0xAD,0x90,0xCB};
/*other host MAC address*/
unsigned char dest_mac[6] = {0x10,0x78,0xD2,0xAD,0x90,0xCB};
/*prepare sockaddr_ll*/
/*RAW communication*/
socket_address.sll_family = PF_PACKET;
/*we don't use a protocoll above ethernet layer
->just use anything here*/
socket_address.sll_protocol = htons(ETH_P_IP);
/*index of the network device
see full code later how to retrieve it*/
socket_address.sll_ifindex = 0;
/*ARP hardware identifier is ethernet*/
socket_address.sll_hatype = ARPHRD_ETHER;
/*target is another host*/
socket_address.sll_pkttype = PACKET_OTHERHOST;
/*address length*/
socket_address.sll_halen = ETH_ALEN;
/*MAC - begin*/
socket_address.sll_addr[0] = 0x10;
socket_address.sll_addr[1] = 0x78;
socket_address.sll_addr[2] = 0xD2;
socket_address.sll_addr[3] = 0xAD;
socket_address.sll_addr[4] = 0x90;
socket_address.sll_addr[5] = 0xCB;
/*MAC - end*/
socket_address.sll_addr[6] = 0x00;/*not used*/
socket_address.sll_addr[7] = 0x00;/*not used*/
memcpy((void*)buffer, (void*)dest_mac, ETH_ALEN);
memcpy((void*)(buffer+ETH_ALEN), (void*)src_mac, ETH_ALEN);
eh->h_proto = 0x00;
int j = 0;
for (j = 46; --j; data[j] = (unsigned char)((int) (255.0*rand()/(RAND_MAX+1.0))));
/*
struct sockaddr_in server;
int len = sizeof(server);
server.sin_family=AF_INET;
server.sin_port=htons(5008);
server.sin_addr.s_addr=inet_addr(host_ip);
int CONN_SOCK = InitSocketTcp(tcp_port);
if(connect(CONN_SOCK, (struct sockaddr*)&server, sizeof(server)) == -1)
{
printf("connection failed\n");
}
else
{
printf("connection ok!\n");
}
*/
while(1)
{
char buff[492] = "\0";
printf("input: ");
scanf("%s", buff);
//send(CONN_SOCK,buff,strlen(buff),0);
/*send the packet*/
send_result = sendto(soc, buff, ETH_FRAME_LEN, 0, (struct sockaddr*)&socket_address, sizeof(socket_address));
send_result == -1?printf("send error"):0;
if(buff[0] == 'q')
{
//shutdown(CONN_SOCK, SD_SEND);
//closesocket(CONN_SOCK);
//WSACleanup();
close(soc);
exit(0);
}
}
}
int main()
{
//for(int i=10; i!=0; --i)
//pthread_create();
task();
return 0;
}
Accept() is only used for TCP or UDP (practically it's main use is in tcp), because it establishes a connection. A connection does 3 way handshake in case of tcp and exchanges information such as sequence numbers etc. and is completely identified by a socket (port plus ip address)
In contrast to that you can simply use sendto and receivefrom api's as normally used in case of udp, where each packet may follow a different path to reach destination. You do not require an accept in case of udp communication. The same can be extended to link layer (L2) frames i.e. each side can send or receive at will without actually establishing a connection first.
This should be done using root