GCC socket functions malfunction

I'm using Linux Mint 14(kernel v3.8.8) with GCC 4.7.3 compiler. Now I've been having some major problems with the GCC socket library functions( connect, accept, and bind). Here is the source code for a simple echo client application:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <netdb.h>
#include <sys/socket1.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <linux/ioctl.h>



#define MAX_BUFFER 1024

void die(char *s)
{
perror(s);
exit(1);
}


int main()

{

int connector,flags,r;
int port;
int set = 1;
struct hostent* host;
struct in_addr in;
struct sockaddr_in rmaddr;
char sendbuffer[MAX_BUFFER];
char recvbuffer[MAX_BUFFER];
char hostname[INET_ADDRSTRLEN];
char* exit = "quit";



if((connector = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0){
perror("socket");
return -1;
}


printf("\n");
printf("Enter the remote hostname(URL/IP4 address): ");
scanf("%s", hostname);
printf("\n");



printf("Enter the port number you wish to connect(on): ");
scanf("%u", &port);
printf("\n");

if(port==0){
printf("ERR0R: Port number must be between 1 & 65,535\n");
printf("\n");
printf("Enter the port number you wish to connect(on): ");
scanf("%u", &port);
printf("\n");
}

host = gethostbyname(hostname);

if(host==NULL){
perror("hostname");
return -1;
}


bzero(&rmaddr,sizeof(rmaddr));
rmaddr.sin_family = AF_INET;
rmaddr.sin_port = htons(port);
bcopy((char*)host->h_addr, (char*)&rmaddr.sin_addr.s_addr, host->h_length);

if(fcntl(connector, F_SETFL, flags | O_NONBLOCK)<0){
perror("ioctl ");
close(connector);
return -1;
}


if(connect(connector,(struct sockaddr*)&rmaddr,sizeof(rmaddr))<0){
perror("connect");
close(connector);
printf("FUCK!\n");
return -1;
}else{
printf("\n");
printf("Connected to host: %s",hostname,"on port %u",port);
printf(" type 'quit' to disconnect\n");
printf("\n");
}

while(1){
int nbr,nbs;
nbr = 0;

printf(">");
scanf("%s",sendbuffer);
printf("\n");

if(sendbuffer==exit){
close(connector);
return 0;
}

nbs = send(connector,(void*)&sendbuffer,strlen(sendbuffer),MSG_NOSIGNAL);

printf("\n");
printf("bytes sent: %i\n",nbs);
printf("\n");

if(nbs < 0){
perror("send() failed");
close(connector);
return -1;
}

while(nbr < nbs){
nbr = recv(connector,(void*)&recvbuffer,strlen(recvbuffer),MSG_NOSIGNAL);
if(nbr < 0){
perror("recv() failed");
close(connector);
return -1;
}else if(nbr==0){
printf("recv(): connection closed prematurely");
close(connector);
return -1;
}else if(nbr > 0){
printf("bytes received: %i\n",nbr);
printf("\n");
printf(">>");
printf("%s",recvbuffer);
printf("\n");

}

}

}

EXIT:
close(connector);
return 0;



}




When I connect to the loopback address on any port number, the connect() returns successfully even if there is no listening socket on the other end! And when I type a message to send and hit enter the send function returns a BROKEN PIPE error. I used netcat to test the network interfaces and they are working just fine so this isn't a kernel problem. The trouble is that the connect call is returning >= 0 even though it's only supposed to return successfully when the 3-way handshake with a listening socket on the other end completes. I think this is a GCC library bug and I might need to rewrite these functions as direct system calls. What do you folks think?



This:
 
if(sendbuffer==exit){

should be:
 
if(strcmp(sendbuffer, exit) == 0){


Regarding:
 
nbs = send(connector,(void*)&sendbuffer,strlen(sendbuffer),MSG_NOSIGNAL);

sendbuffer is an array, so don't take the address of it. Surely the compiler will have warned you (hence the cast). And remove the cast.

You're not initilalising your buffers, so I expect you need to send the null terminator too..

You don't need to specify a flag.

So the corrected line is:
 
nbs = send(connector, sendbuffer, strlen(sendbuffer) + 1, 0);


Regarding line:
 
nbr = recv(connector,(void*)&recvbuffer,strlen(recvbuffer),MSG_NOSIGNAL);

You don't know how much data is comming back, so you need to specify the entire buffer size as the area for the reply to be written into. Plus, recvbuffer isn't initialised, so you have no idea what strlen(recvbuffer) is.

The corrected line is:
 
nbr = recv(connector, recvbuffer, sizeof(recvbuffer), 0);


Oh, I missed this, why are you using non-blocking sockets? Just forget it, comment the section out.
 
//  if(fcntl(connector, F_SETFL, flags | O_NONBLOCK)<0){ 
Last edited on
Topic archived. No new replies allowed.