select() wont timeout after send() - c++

I started to lock into socket programming an got into a little trouble:
I created the small program below which sends a message via udp an receives one if possible in a loop. I want to try that with multiple sockets later on, so I use select().
When I use my 127.0.0.1, select() gives a timeout in the first loop (after send()) but after that it always returns 1 indicating that the socket is readable without receiving a message:
//C++
WSADATA wsa;
SOCKADDR_IN RemoteAddr;
SOCKADDR_IN OwnAddr;
SOCKET UDP_Socket1;
fd_set m_Fds;
struct timeval m_Timeout;
int iRemoteAddrLenght = sizeof(SOCKADDR_IN);
int i = 0;
//--Init
WSAStartup (MAKEWORD (2,2), &wsa);
UDP_Socket1 = socket(AF_INET, SOCK_DGRAM, 0);
m_Timeout.tv_sec = 2;
m_Timeout.tv_usec = 0;
RemoteAddr.sin_family = AF_INET;
RemoteAddr.sin_port = htons (2002);
RemoteAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
OwnAddr.sin_family = AF_INET;
OwnAddr.sin_port = htons (2003);
OwnAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(UDP_Socket1, (SOCKADDR*) &OwnAddr, sizeof(OwnAddr));
for(;;)
{
//..//
//--send
sendto(UDP_Socket1, sSend.c_str(), strlen(sSend.c_str()), 0 , (SOCKADDR*)&RemoteAddr, sizeof(RemoteAddr));
//--select & recv
FD_ZERO(&m_Fds);
FD_SET(UDP_Socket1,&m_Fds);
i = select(sizeof(m_Fds)*8, &m_Fds, NULL, NULL, &m_Timeout);
if(i > 0)
{
recvfrom(UDP_Socket1, m_szBuff, 256, 0, (SOCKADDR*) &RemoteAddr, &m_iRemoteAddrLenght);
} //if
else if(i < 1) // "0" in 1st loop, then "1" =(
{
cout << "Udp Timeout" << endl;
} //else if
} //for
send returns 56 (bytes send)
with WSAGetLastError: 0
recvfrom returns -1
with WSAGetLastError: 10054
I'd appreciate your help about why select() returns 1 when it should timeout

You can ignore these kinds of errors for UDP. Some operating systems report them, some don't. They're basically meaningless.

Related

Berkley Sockets and read timeout

My system is C++ on ARM running Ubuntu.
I am having some problems with Berkley Sockets when I am trying to do a blocking read I get an error and the code is EAGAIN. I put a timer in the code and I find that the error is occurring before the socket timeout. I look at the device that I am connecting too and the socket did not close.
I don't know how this relates but it appears that that this only happens when I am running the program under gdb...at least that is the only time that I have noticed it.
Here is a simplified version of the code. I have taken out the error checking to make it smaller.
int optval;
struct timeval tv;
// Set up the sockaddrIn structures for the port
struct sockaddr_in controlTcpAddr;
memset(&controlTcpAddr, 0, sizeof(controlTcpAddr)); // Clear struct
controlTcpAddr.sin_family = AF_INET; // Internet/IP
controlTcpAddr.sin_addr.s_addr = inet_addr(hostIp); // IP address
controlTcpAddr.sin_port = htons(hostPort); // server port
// Create the TCP socket
myControlTcpSockDesc = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
// Establish connection
connect(myControlTcpSockDesc, (struct sockaddr *) &controlTcpAddr, sizeof(controlTcpAddr);
int flags = fcntl(myControlTcpSockDesc, F_GETFL);
int result = fcntl(myControlTcpSockDesc, F_SETFL, flags & ~O_NONBLOCK);
// Set the SO_REUSEADDR option for the socket
optval = 1;
setsockopt(myControlTcpSockDesc, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)
tv.tv_sec = 10; // 10 Secs Timeout
tv.tv_usec = 0;
setsockopt(myControlTcpSockDesc, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval));
// try a read
cnt = read(myControlTcpSockDesc, myIncomingMsgBuf, MESSAGE_BUFFER_SIZE);
// at this point I find that 10 seconds have not expired
// (I have separate timer running that is not shown)
// cnt = -1
// errno = EAGAIN

Two programs using Select to read socket data, work when they're in different computer but not in the same

I will attempt to be concise while providing the necessary information in order to get the help, from the talented folks here.
The scenario:
Two programs communicate, one (program 2) sends multicast information to the other (program 1), who needs to receive and do some computation and send them back to program 2. Program 2 is multicast capable like mentioned, but also receives unicast, which is the way it receives the data from Program 1.
Program 1: receives in multicast and responds in unicast to program 2
Program 2: sends in multicast and receives in unicast from program 1.
The OS:
Linux Centos
The ISSUE:
The same programs, when i take program 1 to another computer while leaving program 2 in the other and let them communicate over different IP addresses. All is nice and dandy.
But when i run them on the same computer using the same IP address but different Port, they communicate in one socket, but program 2 doesn't see the computed data coming from program 1. Program 1 does calculate and send (sendto return is positive).
I used tcpdump, and effectively nothing coming on the port of program 1, but i can see program 1 having sent the periodic data in socket 1 of program 1.
Now, the fun and concise part:
The code of PROGRAM 1 (PROGRAM 2 is unavailable for disclosure, it is make installed):
struct ConfigStruct
{
struct sockaddr_in Hinfo1, Hinfo2;
struct sockaddr_in Rinfo;
int sock1, sock2;
};
int main()
{
ConfigStruct StructArg;
int fd1, fd2;
int POS(1);
/****************** Network parameters declaration *************************/
// Declaration for socket addresses
struct sockaddr_in Host_info1, Host_info2;
struct sockaddr_in Remote_info;
struct in_addr localInterface;
struct ip_mreq Group;
memset((char *)&Host_info1,0,sizeof(Host_info1));
memset((char *)&Host_info2,0,sizeof(Host_info2));
memset((char *)&Remote_info,0,sizeof(Remote_info));
memset((char *)&Group,0,sizeof(Group));
//**** Reads configuration file****************
cout<<"Reading configuration file..........."<<endl;
std::string input1 ="192.***.**.**";
std::string input2 = "8888";
std::string input3 ="192.***.**.**";
std::string input4 = "8889";
const char* addr_input = input1.data();
const char* port_input = input2.data();
const char* addr_input2 = input3.data();
const char* port_input2 = input4.data();
Remote_info.sin_addr.s_addr=inet_addr(addr_input);
Remote_info.sin_port = htons((uint16_t)stoi(port_input,nullptr,0));
Remote_info.sin_family=AF_INET;
Host_info1.sin_addr.s_addr=inet_addr(addr_input2);//htonl(INADDR_ANY);
Host_info1.sin_port = htons((uint16_t)stoi(port_input2,nullptr,0));
Host_info1.sin_family=AF_INET;
//***** First socket *******
fd1= socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (fd1 == -1)
{
std::cout<<"A problem occured"<<endl;
cease("socket", wd) ;
}
if (setsockopt(fd1,SOL_SOCKET,SO_REUSEADDR, &POS, sizeof(POS)) == -1)
{
perror(" Error in setsockopt");
exit(1);
}
// **** I'M NOT SURE IF THIS NECESSARY **************
int opts;
opts = fcntl(fd1,F_GETFL);
if (opts < 0)
{
perror("fcntl(F_GETFL)");
exit(EXIT_FAILURE);
}
opts = (opts | O_NONBLOCK);
if (fcntl(fd1,F_SETFL,opts) < 0)
{
perror("fcntl(F_SETFL)");
exit(EXIT_FAILURE);
}
//*****************************************************
if (bind(fd1,(struct sockaddr *)&Host_info1,sizeof(Host_info1)) < 0)
{
cease("Bind",wd);
}
else
{
cout<<" Socket ID number "<<fd1<<endl;
cout<<" Bound socket..."<<endl;
}
//********** The multicast network setup ***********************
std::string input5 ="230.*.**.**";
std::string input6 = "192.***.***"; // The same host IP address as above
std::string input7 = "1500" ; // The port number to listen to for Multicast message
const char* Group_Multi_Addr = input5.data();
const char* Group_Interface_Addr = input6.data();
const char* Host_port_input = input7.data();
Group.imr_multiaddr.s_addr = inet_addr(Group_Multi_Addr);
Group.imr_interface.s_addr = inet_addr(Group_Interface_Addr);
Host_info2.sin_family = AF_INET;
Host_info2.sin_addr.s_addr = INADDR_ANY;
Host_info2.sin_port = htons((uint16_t)stoi(Host_port_input,nullptr,0));
//***** The second socket *******
fd2 = socket(AF_INET, SOCK_DGRAM, 0);
if(fd2 < 0)
{
perror("Opening datagram socket error");
exit(1);
}
else
printf("Opening the datagram socket...OK.\n");
int reuse = 1;
if(setsockopt(fd2, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
close(fd2);
cease("Setting SO_REUSEADDR error", wd);
}
else
printf("Setting SO_REUSEADDR...OK.\n");
if(bind(fd2, (struct sockaddr*)&Host_info2, sizeof(Host_info2)))
{
close(fd2);
cease("Binding datagram socket error",wd);
}
else
printf("Binding datagram socket...OK.\n");
if(setsockopt(fd2, IPPROTO_IP, IP_ADD_MEMBERSHIP,(char *)&Group,sizeof(Group)) < 0)
{
perror("Adding multicast group error");
close(fd2);
exit(1);
}
else
printf("Adding multicast group...OK.\n");
StructArg.Hinfo1= Host_info1;
StructArg.Hinfo2= Host_info2 ;
StructArg.Rinfo= Remote_info ;
StructArg.sock1=fd1;
StructArg.sock2=fd2;
fd_set readfds ,rd_fds;
struct timeval tv;
// clear the set ahead of time
FD_ZERO(&readfds);
// add our descriptors to the set
FD_SET(StructArg.sock1, &readfds);
FD_SET(StructArg.sock2, &readfds);
nls = StructArg.sock2 + 1;
char Recv_buffer[125];
char TX_buffer[125];
memset((char *)&Recv_buffer,'0',sizeof(Recv_buffer));
memset((char *)&TX_buffer,'0',sizeof(TX_buffer));
int lenremote(sizeof(StructArg.Rinfo));
ssize_t rs, rs2;
uint8_t MsgSize;
uint8_t MsgID;
int rst;
do
{
do{
rd_fds=readfds;
tv.tv_sec = 0;
tv.tv_usec = 50;
rst = select(nls, &rd_fds, NULL, NULL, &tv);
}while(rst ==-1 && erno==EINTR);
if (rst < 0)
{
perror("select"); // error occurred in select()
}
else
{
// one or both of the descriptors have data
if (FD_ISSET(StructArg.sock1, &rd_fds))
{
rs = recvfrom(StructArg.sock1,....,...,0,...,...) ;
if ( rs > 0 )
{
Do periodic routine work using this unicast socket
}
}
if (FD_ISSET(StructArg.sock2, &rd_fds))
{
rs2 = recv(StructArg.sock2,&Recv_buffer,sizeof(Recv_buffer),0);
if ( rs2 > 0 )
{
send some data to StructArg.sock1
}
}
// THIS IS WHERE I RECEIVE THE MULTICAST FROM PROGRAM 2, AND I DO COMPUTATUIONS , THEN RESPOND USING SOCKET 1 ABOVE (sendto using socket information of the other socket)
}
while(1);
return 0;
}
I am not sure where the problem lies...is it in the configuration of the IP/ports or in Select (i doubt it because it works when in different computers) ???

TCP proxy - mutex

i want to write a simple TCP proxy in C++ for the University. The proxy works with two threads one reads from source port and writes to the destination port and the other thread does the same in the other direction. The aim is to read and manipulate the packets in the future. If i use the mutex to lock the port for read and write on the same port i got package loss. Can you help me to locate the problem because i tried it a long time now?
thread1 = 0;
thread2 = 0;
//Client
struct sockaddr_in address;
int size;
if ((create_socket=socket (AF_INET, SOCK_STREAM, 0)) > 0)
printf ("Socket wurde angelegt\n");
address.sin_family = AF_INET;
address.sin_port = htons (PORT);
inet_aton (IP, &address.sin_addr);
if (connect ( create_socket, (struct sockaddr *) &address, sizeof (address)) == 0)
printf ("Verbindung mit dem Server (%s) hergestellt\n", inet_ntoa (address.sin_addr));
//Server
socklen_t addrlen;
struct sockaddr_in address2;
const int y = 1;
if ((create_socket2=socket (AF_INET, SOCK_STREAM, 0)) > 0)
printf ("Socket wurde angelegt\n");
setsockopt( create_socket2, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int));
address2.sin_family = AF_INET;
address2.sin_addr.s_addr = INADDR_ANY;
address2.sin_port = htons (PORT2);
if (bind ( create_socket2, (struct sockaddr *) &address2, sizeof (address2)) != 0) {
printf( "Der Port ist nicht frei – belegt!\n");
}
listen (create_socket2, 5);
addrlen = sizeof (struct sockaddr_in);
new_socket2 = accept ( create_socket2, (struct sockaddr *) &address2, &addrlen );
if (new_socket2 > 0)
printf ("Ein Client (%s) ist verbunden ...\n", inet_ntoa (address2.sin_addr));
thread apm(apm_gcs);
thread gcs(gcs_apm);
apm.join();
gcs.join();
}
inline void apm_gcs()
{
while (STOP==FALSE)
{
{
lock_guard<mutex> lock(tcp60Mutex);
res = read(create_socket, buffer2, sizeof(buffer2)); // returns after 5 chars have been input
}
{
lock_guard<mutex> lock(tcp65Mutex);
write(new_socket2, buffer2, res);
}
}
}
inline void gcs_apm()
{
while (STOP==FALSE)
{
{
lock_guard<mutex> lock(tcp65Mutex);
res2 = read(new_socket2, buffer, sizeof(buffer)); // returns after 5 chars have been input
}
{
lock_guard<mutex> lock(tcp60Mutex);
write(create_socket, buffer, res2);
}
}
}
Thank you for your help.
Greets
Tobi
There are several things to improve.
First of all: It's not clear what exactly you want to protect. I would understand if you would use one mutex to protect one buffer, and the other mutex for the other buffer, so each buffer will always be accessed by only one thread. However, that does not happen - both threads can read+write the same buffer at the same time. Instead, each mutex protects a socket against read+write at the same time, which is pointless because sockets can handle that perfectly. You can read+write on the same socket at the same time. sockets are used to do that for more than 30 years now.
Once that is changed and your mutexes protect buffers, you will run into blocking again, though less often. You will experience that a thread tries to read or write data while none is available, or the socket connection is full (which happens if you try to quickly write large amounts of data) and it takes time to transfer the data.
This can be solved then by select() or maybe by poll(). Thus the way to go is:
Each thread uses select() or poll() to find out if it can read or write data. Only if it can, it locks the mutex for the buffer, then read or write data (which won't block after select() or poll() made that sure) and then releases the mutex.

setsockopt: Bad file descriptor in C++

I have the famous error "address already in use" because I have no check for the bind function.
Here is my code:
memset(&(this->serv_addr), 0, sizeof(this->serv_addr));
this->serv_addr.sin_family = AF_INET;
this->serv_addr.sin_port = htons(port);
this->serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int yes = 1;
if (setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
But running code I got this:
setsockopt: Bad file descriptor
The code is right, from the guide Beejnet.
But why I got the error?
Maybe the position of the code is wrong?
The first the that sock_fd is called is in the function w_socket:
int retv;
retv = socket(AF_INET, SOCK_STREAM, 0);
if(retv == -1)
{
std::string err_msg(strerror(errno));
err_msg = "[socket] " + err_msg;
throw err_msg;
}
else
{
int reuse_opt = 1;
setsockopt(this->sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse_opt, sizeof(int));
return retv;
}
}
By default there's the sesockopt but no check.
I've tried but it doesn't work.
You need to first create the socket via the socket call, like:
sock_fd = socket(PF_INET, SOCK_STREAM, 0);
(and check the return value; see man 2 socket for details)
Only then you may do your setsockopt call. Before the call to socket, your sock_fd variable will contain a random value (or 0) instead of a socket file descriptor.
Edit after updated question:
Your call to setsockopt needs to use retv instead of this->sock_fd as at that point in time, the this->sock_fd variable is not yet containing the result of your call to socket.

Not able to receive or send entire packet in socket programming using C

I've been trying to send a packet from a client to a server via sockets. With the help of some of the tips I have made quite bit of progress in my code. However, the server only receives eight bytes from the client and prints them on the console whereas at my client side, It seems that it has sent everything.
Now I am not sure whether the problem is at the sending side or the receiving side. My hunch is that something is wrong at my client side. Could someone please help in verifying my assumption?
Client code:
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
data_struct client_data;
struct packet
{
long int srcID;
long int destID;
int pver;
int profiles;
int length;
long int data;
};
if (argc < 3) {
fprintf(stderr,"usage: %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]); //Convert ASCII to integer
sockfd = socket(AF_INET, SOCK_STREAM, 0); // socket file descriptor
if (sockfd < 0)
error("ERROR DETECTED !!! Problem in opening socket\n");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR DETECTED !!!, no such server found \n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr)); //clear the memory for server address
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
printf("Client 1 trying to connect with server host %s on port %d\n", argv[1], portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR in connection");
printf("SUCCESS !!! Connection established \n");
char buffer[256];
struct packet *pkt = (struct packet *) buffer;
char *payload = buffer + sizeof(struct packet);
long double packet_size;
printf("Started Creating packet\n");
pkt->srcID = 01;
pkt->destID = 02;
pkt->pver = 03;
pkt->profiles = 01;
pkt->length = 16;
pkt->data = 1; 2; 3; 4; 5; 6; 7; 8;
{
if (send(sockfd,pkt,sizeof(packet_size),0) <0)
printf ("error\n");
else
printf ("packet send done");
}
return 0;
}
Server code:
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
char wish;
long int SrcID;
long int DestID;
int Pver;
int Profiles;
long int Data;
int Length;
char bytes_to_receive;
int received_bytes;
struct packet
{
long int srcID;
long int destID;
int pver;
int profiles;
int length;
long int data;
};
if (argc < 2) {
fprintf(stderr,"usage: %s port_number1",argv[0]);
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR DETECTED !!! Problem in opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR DETECTED !!! There was a problem in binding");
listen(sockfd, 10);
clilen = sizeof(cli_addr);
printf("Server listening on port number %d...\n", serv_addr.sin_port);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR DETECTED !!! the connection request was not accepted");
char buffer[256];
struct packet *pkt = (struct packet *) buffer;
char *payload = buffer + sizeof(struct packet);
long double packet_size;
bytes_to_receive = sizeof(packet_size);
received_bytes = 0;
int rc =0;
while ((rc = recv(newsockfd,pkt,sizeof(packet_size),0)) > 0)
{
received_bytes+=rc;
SrcID = pkt->srcID;
DestID = pkt->destID;
Pver = pkt->pver ;
Profiles = pkt->profiles;
Length = pkt->length;
Data = pkt->data;
printf("Data Received from Client_1 are :\n");
printf("Source ID: %ld\n", SrcID);
printf("Destination ID: %ld\n", DestID);
printf("profile Version: %d\n", Pver);
printf("No of Profiles: %d\n", Profiles);
printf("Length: %d\n", Length);
printf("data : %ld\n", Data);
}
if (rc == 0)
{
printf("Connection closed by Server\n");
printf("Bytes received: %d\n",received_bytes);
}
if (rc == -1)
{
perror("recv");
}
{
if (close(newsockfd) == -1) {
error("Error closing connection with client 1");
}
printf("Connection with client 1 has been closed\n");
}
return 0;
}
The output that I see on the client's console is:
Client Side: Client 1 trying to connect with server host 130.191.166.230 on port 1234
SUCCESS !!! Connection established
Started Creating packet
packet send done
and on the server's console I see:
Server Side: Data Received from Client_1 are :
Source ID: 1
Destination ID: 2
profile Version: 0
No of Profiles: 1074462536
Length: 0
data : 0
Connection closed by Server
Bytes received: 8
Connection with client 1 has been closed
First of all
recv(newsockfd,pkt,sizeof(packet_size),0)) /* What is packet_size ? */
recv(newsockfd,pkt,sizeof(struct packet),0)) /* You probably mean this. */
That might solve your problems, but there are a few issues with the way you are using TCP sockets.
But at my client side, it prints that it has sent everything
Where ? I don't see you actually checking the number of bytes sent. send(2) can return after sending less that you asked it to.
It shows me that only 8 bytes were sent by Client and prints them out.
TCP is a stream-oriented protocol. You send bytes and they arrive, in the same order. So when you recv(2) something, you might get less (or more than you wrote). So, the following can be true:
client:
send 100 bytes
send 400 bytes
server:
recv 50 bytes
recv 150 bytes
recv 250 bytes
recv 50 bytes
The number of send and recv calls need not be identical when using TCP.
When you call send the function returns the number of bytes actually sent and this number can be less than the number of bytes you wanted to send. So every time you want to send something there must be a loop like the following
bool sendBuffer(SOCKET s, unsigned char *buf, int size)
{
while (size > 0)
{
int sz = send(s, buf, size,0);
if (sz < 0) return false; // Failure
size -= sz; // Decrement number of bytes to send
buf += sz; // Advance read pointer
}
return true; // All buffer has been sent
}
and a similar loop must be done when receiving (in other words recv can return less bytes than what you are asking for).
If you don't make these loops the risk is that everything apparently will work anyway (until the size of an ethernet packet) when you work on your local machine or even over a LAN, but things will not work when working across the internet.
Note also that as other answers pointed out you asked to send sizeof(packet_size) i.e. the number of bytes required to store that variable, not the size of the structure.
There is an informal rule that nobody is allowed to write any software that uses TCP until they memorize this sentence and can fully explain what it means: "TCP is a byte-stream protocol that does not preserve application message boundaries."
What that means is that TCP only ensures that you get out the same bytes you put in and in the same order. It does not "glue" the bytes together in any way.
Before you write any code that uses TCP, you should either use a protocol that is already designed (such as IMAP or HTTP) or design one yourself. If you design one yourself, you should write out a protocol specification. It should specifically define what a protocol-level message will consist of at the byte level. It should specifically state how the receiver finds the ends of messages, and so on.
This may seem a little silly for simple applications, but trust me, it will pay off massively. Otherwise, it's almost impossible to figure out why things aren't work because if the server and client don't quite get along, there's no arbiter to say what's right.
I don't specialise in socket programming but there are a few things I've noticed. As far as I'm aware, I don't think you can send structs over sockets that easily. You may wish to consider a different method.
NB, when using send/recv you're also determing the sizeof packet_size, and not the sizeof the struct.
Googling brought up this about sending structs over sockets: http://ubuntuforums.org/showthread.php?t=613906