Why do I get an unexpected port value in C? - c

I'm writing a program which gets an identifier from params, creates an UDP socket, gets a port, and prints <identifier>: <port>.
Then, receives some identifiers and ports from stdin and store them in memory.
In the code below, the problem is that the port variable (udp_port) get 0.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
typedef struct process {
char id[80];
int port;
int me;
} process;
int main(int argc, char* argv[]) {
if(argc<2) {
fprintf(stderr,"Use: process <ID>\n");
return 1;
}
/* NODES */
process * processes;
int num_process = 0;
/* CONECTION */
int udp_port;
int fd;
struct sockaddr_in addr, local_addr;
/* STDIN READS */
int port;
char line[80],proc[80];
/* I/O buffer mode */
setvbuf(stdout,(char*)malloc(sizeof(char)*80),_IOLBF,80);
setvbuf(stdin,(char*)malloc(sizeof(char)*80),_IOLBF,80);
/* Prepare socket */
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(0);
addr.sin_addr.s_addr = INADDR_ANY;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if(fd == -1){
perror("SOCKET");
return 1;
}
if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1){
perror("BIND");
return 1;
}
getsockname(fd, (struct sockaddr *)&local_addr, (socklen_t *) sizeof(struct sockaddr));
udp_port=ntohs(local_addr.sin_port); // Gets port
fprintf(stdout,"%s: %d\n",argv[1],udp_port); // Prints identifier: port
// Reads from stdin
for(;fgets(line,80,stdin);) {
if(!strcmp(line,"START\n"))
break;
sscanf(line,"%[^:]: %d",proc,&port);
num_process++;
processes = realloc(processes,num_process);
strcpy(processes[num_process-1].id, proc);
processes[num_process-1].port = port;
if(!strcmp(proc,argv[1])){ /* Thats me */
processes[num_process-1].me = 1;
}else{
processes[num_process-1].me = 0;
}
}
return 0;
}
But, it gets a correct value (random port) when I comment the realloc line and related lines, like this:
// Reads from stdin
for(;fgets(line,80,stdin);) {
if(!strcmp(line,"START\n"))
break;
sscanf(line,"%[^:]: %d",proc,&port);
num_process++;
//processes = realloc(processes,num_process);
//strcpy(processes[num_process-1].id, proc);
//processes[num_process-1].port = port;
if(!strcmp(proc,argv[1])){ /* Thats me */
// processes[num_process-1].me = 1;
}else{
// processes[num_process-1].me = 0;
}
}

Your code crashes if used as it is. Because you pass to realloc uninitialized pointer. Initialize processes to NULL:
process * processes = NULL;
EDIT:
Otherwise, the udp_port is non zero. And getsockname returns Bad address.
Try the following for getsockname to be successsful:
socklen_t tmp = sizeof(struct sockaddr);
getsockname (fd, (struct sockaddr *) &local_addr,&tmp);

Checking the return value of getsockname function I get a Bad address error.
The problem was that the last parameter in getsockname was incorrect:
getsockname(fd, (struct sockaddr *)&local_addr, (socklen_t *) sizeof(struct sockaddr));
sizeof returns a socklen_t instead of socklen_t *. I fixed this like this:
socklen_t size_sa = sizeof(struct sockaddr);
if(getsockname(fd, (struct sockaddr *)&local_addr, &size_sa) == -1){
perror("GETSOCKNAME");
return 1;
}

Related

UDP Client Server invalid argument

I have a server that is supposed to send information to a client after receiving a message from the client (echo server). Below is the code that is producing an errno 22 which i looked up as "invalid argument". I am trying to understand which argument is invalid because my client sends a message with the same arguments
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
//#include <sys/time.h>
int main(int argc, char *argv[]) {
// port to start the server on
int SERVER_PORT = 8877;
struct timeval server_start, client_start;
// socket address used for the server
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
// htons: host to network short: transforms a value in host byte
// ordering format to a short value in network byte ordering format
server_address.sin_port = htons(SERVER_PORT);
// htons: host to network long: same as htons but to long
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
// create a UDP socket, creation returns -1 on failure
int sock;
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
printf("could not create socket\n");
return 1;
}
// bind it to listen to the incoming connections on the created server
// address, will return -1 on error
if ((bind(sock, (struct sockaddr *)&server_address,
sizeof(server_address))) < 0) {
printf("could not bind socket\n");
return 1;
}
// socket address used to store client address
struct sockaddr_in client_address;
int client_address_len = 0;
// run indefinitely
while (true) {
char buffer[500];
printf("problem here \n");
int len=0;
// read content into buffer from an incoming client
if (len = recvfrom(sock, &client_start, sizeof(client_start), 0,(struct sockaddr *)&client_address,&client_address_len)<0){
printf("failed: %d\n", errno);
return 1;
}
// inet_ntoa prints user friendly representation of the
// ip address
//buffer[len] = '\0';
gettimeofday(&server_start);
int send = 0;
// send same content back to the client ("echo")
if(send = sendto(sock, &server_start, sizeof(server_start),0,(struct sockaddr *)&client_address,
&client_address_len)<0){
printf("failed: %d\n", errno);
return 1;
};
}
return 0;
}
I am trying to understand which argument is invalid
No argument is invalid. You got a false positive on your error testing.
if (len = recvfrom(sock, &client_start, sizeof(client_start), 0,(struct sockaddr *)&client_address,&client_address_len)<0){
if(send = sendto(sock, &server_start, sizeof(server_start),0,(struct sockaddr *)&client_address,
&client_address_len)<0){
Usual problem. Operator precedence. Try this:
if ((len = recvfrom(sock, &client_start, sizeof(client_start), 0,(struct sockaddr *)&client_address,&client_address_len))<0){
if((send = sendto(sock, &server_start, sizeof(server_start),0,(struct sockaddr *)&client_address,
&client_address_len))<0){

Segmentation Fault in UDP

I got a segmentation fault problem when I write a client-server project in UDP. It happens on server side, when I receive a packet from client and going to send an ACK back. I tried to search the solutions and got UDP Server giving Segmentation Fault and C concurrent UDP socket , weird segmentation fault, but seems both of those are not the answer I'm looking for.
Here is my server side code
#include <ctype.h> /* for toupper */
#include <stdio.h> /* for standard I/O functions */
#include <stdlib.h> /* for exit */
#include <string.h> /* for memset */
#include <sys/socket.h> /* for socket, sendto, and recvfrom */
#include <netinet/in.h> /* for sockaddr_in */
#include <unistd.h> /* for close */
#define STRING_SIZE 1024
#define SERV_UDP_PORT 12311
int main(void) {
int sock_server;
struct sockaddr_in server_addr;
unsigned short server_port;
struct sockaddr_in client_addr;
unsigned int client_addr_len;
char sentence[STRING_SIZE];
char modifiedSentence[STRING_SIZE];
unsigned int msg_len;
int bytes_sent, bytes_recd;
unsigned int i;
struct Pkt
{
short length;
short seqnum;
char databytes[80];
};
struct Pkt* pkt;
int j ; //for loop
int seq;
short num_of_bytes;
//char ack_num[2];
struct Ack
{
short ack_num;
};
struct Ack* ack;
/* open a socket */
if ((sock_server = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("Server: can't open datagram socket\n");
exit(1);
}
/* initialize server address information */
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl (INADDR_ANY);
server_port = SERV_UDP_PORT;
server_addr.sin_port = htons(server_port);
/* bind the socket to the local server port */
if (bind(sock_server, (struct sockaddr *) &server_addr,
sizeof (server_addr)) < 0) {
perror("Server: can't bind to local address\n");
close(sock_server);
exit(1);
}
/* wait for incoming messages in an indefinite loop */
printf("Waiting for incoming messages on port %hu\n\n",
server_port);
client_addr_len = sizeof (client_addr);
for (;;) {
bytes_recd = recvfrom(sock_server, pkt, sizeof(*pkt), 0, (struct sockaddr *) &client_addr, &client_addr_len);
ack->ack_num = pkt->seqnum;
printf("%02d\n", ack->ack_num);
num_of_bytes = pkt->length;
printf("The sequence number is: %d\n", ack->ack_num);
printf("Received Sentence is: %s\n with length %d\n\n", pkt->databytes, num_of_bytes);
msg_len = 3;
/* send message */
bytes_sent = sendto(sock_server, (struct Ack*)&ack, msg_len, 0, (struct sockaddr*) &client_addr, client_addr_len); //Here is the segmentation fault comes from
}
}
I'm not really good at C, so forgive me if the code is silly.
Please point out anything wrong or just looks weird.
Thanks in advance for any help.
pkt is pointer to a Pkt, but you haven't initialized it. Likewise with ack. You can either a) malloc a Pkt and assign the result to pkt, or b) change pkt to be a Pkt structure (rather than a pointer). The second option would look something like:
struct Pkt pkt;
struct Ack ack;
bytes_recd = recvfrom(sock_server, &pkt, sizeof(pkt), 0, (struct sockaddr *) &client_addr, &client_addr_len);
ack.ack_num = pkt.seqnum;
printf("%02d\n", ack.ack_num);
num_of_bytes = pkt.length;
printf("The sequence number is: %d\n", ack.ack_num);
printf("Received Sentence is: %s\n with length %d\n\n", pkt.databytes, num_of_bytes);
/* send message */
bytes_sent = sendto(sock_server, &ack, sizeof(ack), 0, (struct sockaddr*) &client_addr, client_addr_len);

TCP Linux server lock after the first accept

I am writing a TCP client in C.
Following several tutorial I wrote my code but it can accept only the first connection to the server.
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h> //inet_addr for INADDR_ANY
#include <string.h> //for splitting (strtok)
#include <pthread.h> //thread library
#include <time.h>
#include <unistd.h> //for function close()
void* SocketHandler(void*);
int main(void) {
//socket parameters
int server_socket_desc;
int clientAddressLength = sizeof(struct sockaddr_in);
struct sockaddr_in server_addr, client_addr;
const unsigned short int PORT_NUMBER = 8963;
server_socket_desc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket_desc < -1) {
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server_addr.sin_family = AF_INET; //it should be always set to AF_INET
//set the server address
server_addr.sin_addr.s_addr = inet_addr("192.168.123.240");
//server_addr.sin_addr.s_addr = inet_addr("31.185.101.35");
//server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(PORT_NUMBER);
//Bind
if (bind(server_socket_desc, (struct sockaddr *) &server_addr,
sizeof(server_addr)) < 0) {
//print the error message
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(server_socket_desc, 10);
//Accept and incoming connection
puts("Waiting for incoming connections...");
//accept connection from an incoming client
while (1) {
int *temp_socket_desc = (int*) malloc(sizeof(int));
if ((*temp_socket_desc = accept(server_socket_desc,
(struct sockaddr *) &client_addr,
(socklen_t*) &clientAddressLength)) != -1) {
printf("----------\nConnection accepted \n");
sleep(1);
pthread_t thread_id;
int *client_socket_desc = (int*) malloc(sizeof(int));
client_socket_desc = temp_socket_desc;
pthread_create(&thread_id, NULL, &SocketHandler,
(void*) client_socket_desc);
//if thread has not terminated, pthread_detach() shall not cause it to terminate
pthread_detach(thread_id);
puts("handler assigned");
} else
puts("connection refused");
}
close(server_socket_desc);
//mysql_close(mysql_conn);
return 0;
}
/*
* This will handle connection for each client
* */
void* SocketHandler(void* lp) {
int *csock = (int*) lp;
char buffer[128];
int buffer_len = 128;
int bytecount;
memset(buffer, 0, buffer_len);
if ((bytecount = read(*csock, buffer, buffer_len) == -1)) {
fprintf(stderr, "Error receiving data\n");
close(*csock);
return 0;
}
printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
close(*csock);
free(csock);
puts("exiting thread");
//pthread_exit(0);
return 0;
}
I temporally solved the problem inserting a sleep() after the while loop but it is a very bad solution.
Can somebody explain me why the code does'n work without the sleep?
There is a problem in handling of client_socket_desc:
You allocate it only once. All threads will get the same pointer.
So later accepts will override socket descriptors value of earlier threads.
Try the following change, for allocating own memory block for each thread:
int fd = accept( server_socket_desc, (struct sockaddr *) &client_addr, (socklen_t*)
&clientAddressLength)
if ( fd != -1 )
{
pthread_t thread_id;
int *client_socket_desc = malloc(sizeof(int));
*client_socket_desc = fd;
pthread_create(&thread_id, NULL, &SocketHandler,(void*) client_socket_desc);
...
Or course you must add error handlings for malloc and pthread_create.
And also free the allocated memory when not needed anymore.
I don't understood why there is the following code in the while loop:
if(send(*client_socket_desc,buffer,1,MSG_NOSIGNAL)>0)
{
puts("closing client socket");
close(*client_socket_desc);
}
Close client sockets in client handler threads.

C socket not running on Mac OS X

The following code runs and communicates with the client without a problem on Ubuntu. However, I need to run on Mac OS X. I can compile it with no errors however when I am trying to run it the following message appears: "Abort trap: 6". I tried to google it but cannot find any useful information about it. Even if I put a printf in the beginning of the main function it does not run. Thank you for any suggestion.
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#define UNIX_PATH_MAX 108
int connection_handler(int connection_fd)
{
int nbytes;
char buffer[256];
nbytes = read(connection_fd, buffer, 256);
buffer[nbytes] = 0;
printf("MESSAGE FROM CLIENT: %s\n", buffer);
nbytes = snprintf(buffer, 256, "hello from the server");
write(connection_fd, buffer, nbytes);
close(connection_fd);
return 0;
}
int main(void)
{
struct sockaddr_un address;
int socket_fd, connection_fd;
socklen_t address_length;
pid_t child;
socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if(socket_fd < 0)
{
printf("socket() failed\n");
return 1;
}
unlink("./demo_socket");
/* start with a clean address structure */
memset(&address, 0, sizeof(struct sockaddr_un));
address.sun_family = AF_UNIX;
snprintf(address.sun_path, UNIX_PATH_MAX, "./demo_socket");
if(bind(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0)
{
printf("bind() failed\n");
return 1;
}
if(listen(socket_fd, 5) != 0)
{
printf("listen() failed\n");
return 1;
}
while((connection_fd = accept(socket_fd, (struct sockaddr *) &address,&address_length)) > -1)
{
child = fork();
if(child == 0)
{
/* now inside newly created connection handling process */
return connection_handler(connection_fd);
}
/* still inside server process */
close(connection_fd);
}
close(socket_fd);
unlink("./demo_socket");
return 0;
}
You have UNIX_PATH_MAX hard-coded to 108, but sun_path in sockaddr_un is only 104 bytes long:
struct sockaddr_un {
unsigned char sun_len; /* sockaddr len including null */
sa_family_t sun_family; /* [XSI] AF_UNIX */
char sun_path[104]; /* [XSI] path name (gag) */
};
So you're trying to write outside the buffer with the following:
snprintf(address.sun_path, UNIX_PATH_MAX, "./demo_socket");
You can fix this with:
snprintf(address.sun_path, sizeof(address.sun_path), "./demo_socket");
This would have been an easy fix if you had used a debugger (such as gdb).
A possible cause is that you don't initialize address_length before calling accept. accept needs it to be properly initialized before the call.

Socket program gives "Transport endpoint is already connected" error

I am trying to create a very simple client-server chat program, where two programs can communicate with each other. However, the accept function is giving me the error "invalid argument". I am pasting the code here:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
int main()
{
struct sockaddr_in myaddr;
struct sockaddr_in otheraddr;
int sockid;
int bindid;
int recvsockid;
int clientlen;
int connectid;
char send_msg[100] = "Program 1", recv_msg[100];
int recvid, sendid;
int myport_id = 4550;
int otherport_id = 4560;
sockid = socket(AF_INET, SOCK_STREAM, 0);
//fcntl(sockid, F_SETFL, O_NONBLOCK);
if (sockid < 0)
{
printf("\nCould not create socket");
}
bzero((char*)&myaddr, sizeof(struct sockaddr_in));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
myaddr.sin_port = htons(myport_id);
bzero((char*)&otheraddr, sizeof(struct sockaddr_in));
otheraddr.sin_family = AF_INET;
otheraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
otheraddr.sin_port = htons(otherport_id);
bindid = bind(sockid, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in));
if(bindid < 0)
printf("bind error \n");
listen(bindid, 5);
do
{
connectid = connect(sockid, (struct sockaddr*)&otheraddr, sizeof(struct sockaddr_in));
if (connectid < 0 && !(errno == EINPROGRESS))
{
//printf("%s", strerror(errno));
perror("connect");
exit(1);
}
recvsockid = accept(sockid, (struct sockaddr*)&myaddr, &clientlen);
if (recvsockid < 0 && !(errno == EINPROGRESS || errno == EAGAIN))
{
perror("accept");
exit(1);
}
} while (connectid < 0 && recvsockid < 0);
do
{
gets(send_msg);
sendid = sendto(sockid, send_msg, 100, 0, (struct sockaddr*)&otheraddr, sizeof(struct sockaddr_in));
fprintf(stderr, "%d", sendid);
if(sendid < 0)
printf("error3\n");
recvid = recvfrom(recvsockid, recv_msg, 100, 0, (struct sockaddr*)&myaddr, &clientlen);
if (recvid < 0)
{
printf("\nError in receive");
break;
}
} while (1);
return 0;
}
I will be grateful if someone could tell me why I am getting this error, and how to correct it.
Thanks a lot.
Your problem is that you are trying to connect and to listen on the same socket sockid. I'm pretty sure you meant bindid for listening.
Edit 0:
Since you are creating both sides of the TCP connection in the same program, you need two socket descriptors, i.e. two calls to socket(2) in the setup code, one for connecting and one for accepting client connections.
recvsockid = accept(sockid, (struct sockaddr*)&myaddr, &clientlen);
You have not initialized clientlen, if you look at the documentation for accept():
address_len
Points to a socklen_t structure which on input specifies the length of the supplied sockaddr structure, and on output specifies
the length of the stored address.
So, set it to the length of myaddr prior to calling accept():
client_len = sizeof myaddr;
recvsockid = accept(sockid, (struct sockaddr*)&myaddr, &clientlen);

Resources