I'm trying to write a client server program using UDP, and wait-and-stop, but I haven't got to that part, I'm still trying to figure it out how the two processes (server and client) communicate, because on my client program, the user needs to enter the server name or IP address, and a port name, and then send an expression that the server should calculate. However, I dug some tutorials in the internet and after coding accordingly (or I thought so) I can't make the client communicate with the server. Below is my code, please enlighten me what I'm doing wrong, if it's the bind(), sendto(), recvfrom() or socket(), or all of them. I can't see what exactly is wrong. I know that the client-side shouldn't run on a infinite loop, but so far I want to make the programs communicate with each other, afterwards I'll polish my code. Thanks!
client-side code:
#include <stdio.h> // Default System Calls
#include <stdlib.h> // Needed for OS X
#include <string.h> // Needed for Strlen
#include <sys/socket.h> // Needed for socket creating and binding
#include <netinet/in.h> // Needed to use struct sockaddr_in
#include <time.h> // To control the timeout mechanism
#define EXPR_SIZE 1024
#define BUFLEN 512
#define TRUE 1
#define FALSE 0
#define SERVERLEN 1024
int main(int argc, char **argv){
long portNum; // Since it's possible to input a value bigger
// than 65535 we'll be using long to
// avoid overflows
char expr[EXPR_SIZE];
char server[SERVERLEN];
int fd; // file descriptor for the connected socket
int buf[512];
struct hostent *h; // information of the host
unsigned int addrLen; // address length after getting the port number
struct sockaddr_in myaddr; // address of the client
struct sockaddr_in servaddr; // server's address
unsigned int exprLen;
socklen_t slen = sizeof(servaddr);
printf("Enter server name or IP address:");
scanf("%s",server);
printf("Enter port:");
scanf("%ld",&portNum);
if ((portNum < 0) || (portNum > 65535)) {
printf("Invalid port number. Terminating.");
return 0;
}
printf("Enter expression:");
scanf("%s",expr);
if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
perror("cannot create socket");
return 0;
}
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
if(bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0){
perror("cannot bind");
return 0;
}
/*
// Discovering the port number the OS allocated
addrLen = sizeof(myaddr);
if(getsockname(fd, (struct sockaddr *)&myaddr, &addrLen) < 0){
perror("cannot getsockname");
return 0;
}
printf("local port number = %d\n", ntohs(myaddr.sin_port));
*/
memset((char*)&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htonl(portNum);
exprLen = sizeof(expr);
while(TRUE){
printf("Sending message to %s port %ld\n",server, portNum);
if (sendto(fd, expr, strlen(expr), 0, (struct sockaddr *)&servaddr, slen) < 0) {
perror("cannot sendto()");
}
printf("Success\n");
}
return 0;
}
Server-side code:
#include <stdio.h> // Default System Calls
#include <stdlib.h> // Needed for OS X
#include <string.h> // Needed for Strlen
#include <sys/socket.h> // Needed for socket creating and binding
#include <netinet/in.h> // Needed to use struct sockaddr_in
#include <time.h> // To control the timeout mechanism
#define EXPR_SIZE 1024
#define BUFLEN 512
#define TRUE 1
#define SERVERLEN 1024
int main(int argc, char **argv){
struct sockaddr_in myaddr; // address of the server
struct sockaddr_in claddr; // address of the client
char buf[BUFLEN];
int fd;
long recvlen;
socklen_t clientlen;
if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
perror("cannot create socket");
return 0;
}
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
if(bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0){
perror("cannot bind");
return 0;
}
clientlen = sizeof(claddr);
while (TRUE) {
recvlen = recvfrom(fd, buf, BUFLEN, 0, (struct sockaddr *)&claddr, &clientlen);
if (recvlen < 0) {
perror("cannot recvfrom()");
return 0;
}
printf("Received %ld bytes\n",recvlen);
buf[recvlen] = 0;
printf("Received message: \"%s\"\n",buf);
}
return 0;
}
The server program doesn't output anything, while the client outputs until the process is interrupted:
Enter server name or IP address:127.0.0.1
Enter port:30
Enter expression:2+2
Sending message to 127.0.0.1 port 30
cannot sendto(): Can't assign requested address
I tried changing the server name to localhost, and other ports, but to no avail.
When developing networking software (especially when using the BSD socket interface), it's important to keep things as simple as possible until you've established basic communication. Then you can incrementally add functionality, while making sure that you don't break anything along the way.
On the client side, keeping things simple means
Don't call bind in the client. The OS will choose an appropriate interface and assign a random port number, so there's no need to bind the socket.
Use a hard-coded server address (e.g. 127.0.0.1). Address 127.0.0.1 (0x7f000001) is the local host address, suitable for sending packets to a server on the same machine.
Use a hard-coded port number (e.g. 50037). Ephemeral port numbers should be greater than 0xC000 hex (49152 decimal).
Use a hard-coded message, e.g. "hello".
With that in mind, here's what the client software looks like
int main( void )
{
int fd;
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket failed");
return 1;
}
struct sockaddr_in serveraddr;
memset( &serveraddr, 0, sizeof(serveraddr) );
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons( 50037 );
serveraddr.sin_addr.s_addr = htonl( 0x7f000001 );
for ( int i = 0; i < 4; i++ ) {
if (sendto( fd, "hello", 5, 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
perror( "sendto failed" );
break;
}
printf( "message sent\n" );
}
close( fd );
}
On the server side, keeping things simple means
Bind to INADDR_ANY, i.e. let the OS pick an appropriate interface.
Bind to a hard-coded port, e.g. 50037 (must be the same port the client uses).
Don't request the address information from recvfrom, i.e. pass NULL, 0 as the last two parameters.
With that in mind, here's what the server software looks like
int main( void )
{
int fd;
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror( "socket failed" );
return 1;
}
struct sockaddr_in serveraddr;
memset( &serveraddr, 0, sizeof(serveraddr) );
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons( 50037 );
serveraddr.sin_addr.s_addr = htonl( INADDR_ANY );
if ( bind(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
perror( "bind failed" );
return 1;
}
char buffer[200];
for ( int i = 0; i < 4; i++ ) {
int length = recvfrom( fd, buffer, sizeof(buffer) - 1, 0, NULL, 0 );
if ( length < 0 ) {
perror( "recvfrom failed" );
break;
}
buffer[length] = '\0';
printf( "%d bytes: '%s'\n", length, buffer );
}
close( fd );
}
Related
TCP socket demultiplexing at the server port (which listens for multiple TCP connections) happens with a separate socket descriptor created for each established TCP connection(though the accept() call) and the socket descriptor is tightly coupled with tuple [source IP address, source port, destination IP address, destination IP address]. Over this established connection we can use the high layer application protocols like HTTP, FTP, SSH etc.,
But in case of UDP there is no session/connection established between the peers. The server waiting at the particular port receives the message from any client. The client's IP address and port number is known after receiving the message(populated in the socket address structure). From the address structure the messages can be demultiplexed and given to respective applications.
Over the server port, If I want to establish a connected session over UDP[like the tuple mentioned in case of TCP] so that communication between the server and client (between particular port on server and client) can be demultiplexed before receiving the message(without inferring the same from socket address structure) so that the higher layer protocols can work like on TCP (ofcourse higher layer protocols like DTLS taking care of the reliability)
Below is the code for UDP server(leveraging the connect() API to keep the UDP socket connected) and UDP client
// server program for udp connection
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PORT 5000
#define MAXLINE 1000
//logical thread num
static unsigned int threadnum = 0;
struct pass_info {
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
unsigned int threadnum;
};
char *message = "Hello Client";
void* connection_handle(void *info) {
int fd = 0;
char buffer[100];
int n = 0;
const int on = 1;
struct pass_info *pinfo = (struct pass_info*) info;
printf("Executing thread : %d\n", pinfo->threadnum);
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
printf("Error socket!!!");
return;
}
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on));
bind(fd, (const struct sockaddr *) &pinfo->server_addr, sizeof(struct sockaddr_in));
connect(fd, (struct sockaddr *) &pinfo->client_addr, sizeof(struct sockaddr_in));
while(1)
{
n = recv(fd, buffer, sizeof(buffer), 0);
if (n < 0)
{
printf("receive failed! in thread : %d", pinfo->threadnum);
break;
}
buffer[n] = '\0';
printf("Thread num %d: Recv message - %s\n", pinfo->threadnum, buffer);
n = send(fd, message, sizeof(message), 0);
if (n < 0)
{
printf("send failed! in thread : %d", pinfo->threadnum);
break;
}
}
free(info);
return NULL;
}
int main()
{
char buffer[100];
int listenfd, len, sockfd;
const int on = 1;
struct sockaddr_in servaddr, cliaddr;
bzero(&servaddr, sizeof(servaddr));
struct pass_info *info;
pthread_t tid;
// Create a UDP Socket
listenfd = socket(AF_INET, SOCK_DGRAM, 0);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
servaddr.sin_family = AF_INET;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on));
// bind server address to socket descriptor
bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
while (1)
{
//receive the datagram
len = sizeof(cliaddr);
int n = recvfrom(listenfd, buffer, sizeof(buffer),
0, (struct sockaddr*)&cliaddr,&len); //receive message from server
buffer[n] = '\0';
printf("Main thread: Recv message - %s\n", buffer);
n = sendto(listenfd, message, MAXLINE, 0, (struct sockaddr*)&cliaddr, sizeof(cliaddr));
info = (struct pass_info*) malloc (sizeof(struct pass_info));
memcpy(&info->server_addr, &servaddr, sizeof(struct sockaddr_in));
memcpy(&info->client_addr, &cliaddr, sizeof(struct sockaddr_in));
threadnum++;
info->threadnum = threadnum;
if (pthread_create(&tid, NULL, connection_handle, info) != 0) {
perror("pthread_create");
exit(-1);
}
}
}
// udp client program
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
#define PORT 5000
#define MAXLINE 1000
int main()
{
char buffer[100];
char *message = "Hello Server";
int sockfd, n;
struct sockaddr_in servaddr, cliaddr;
int len = 0;
// clear servaddr
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT);
servaddr.sin_family = AF_INET;
// create datagram socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
while(1)
{
sleep(3);
sendto(sockfd, message, MAXLINE, 0, (struct sockaddr*)&servaddr, sizeof(servaddr));
// waiting for response
recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&cliaddr, &len);
puts(buffer);
}
}
Queries:
Whether this would be the right way to do de-multiplexing at the UDP socket level
The server listens for any UDP packets from the client. once it receives a message, new socket descriptor is created and the connect() API is called so that the client's IP address, port is registered with this newly created socket descriptor and from here on newly created socket descriptor will used to send and receive messages to the particular client's IP address and port. Whether it is a fool proof method
Are there any other well known methods to use the higher layer protocols(protocols supporting reliability like DTLS) over UDP
I wrote a server code as the main server for all the clients. This program is multi-threaded and waits for the clients to connect. Once all the threads are created, they wait on thread accept. Once the connection is accepted, they wait on reception of file from clients. At the end of these threads reception, all the threads join so that system is at common point. This behavior repeats after every 40 seconds.
I need to capture video frames and transferring then integrated in the code?
Server.c
// Server side C/C++ program to demonstrate Socket programming
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include<pthread.h> //for threading , link with lpthread
#define LISTENING_PORT 8080
#define CLIENT_COUNT 4
void * handle_new_conn(void *server_fd)
{
int valread;
char buffer[1024] = {0};
char *hello = "Hello from server";
int new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( LISTENING_PORT );
/* Accept connection from client */
if ((new_socket = accept(*((int *)server_fd),
(struct sockaddr *)&address,
(socklen_t*)&addrlen)) < 0)
{
perror("accept");
exit(EXIT_FAILURE);
}
/* Code to handle new connection */
valread = read(new_socket, buffer, 1024);
printf("%s\n", buffer);
sleep(10);
send(new_socket, hello , strlen(hello), 0);
printf("Hello message sent\n");
sleep(2);
close(new_socket);
}
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "Hello from server";
pthread_t thread_id[4];
int client_no = 0;
int i;
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( LISTENING_PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, CLIENT_COUNT - 1) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
while (1)
{
for (i=0; i < CLIENT_COUNT; i++)
{
/* Handle the accepted connection from client */
if (pthread_create(&thread_id[client_no] , NULL,
handle_new_conn, (void*) &server_fd) < 0)
{
perror("Couldn't create thread");
exit(EXIT_FAILURE);
}
client_no++;
}
client_no = 0;
for (i=0; i < CLIENT_COUNT; i++)
{
pthread_join(thread_id[client_no], NULL);
printf("Thread [%d] destroyed\n",
thread_id[client_no]);
client_no++;
}
/* Wait for the next interval to fetch the feed */
sleep(40);
}
return 0;
}
client.c
// Client side C/C++ program to demonstrate Socket programming
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#define SERVER_PORT 8080
void record_video()
{
/* Record video that has to be transmitted */
}
void handle_request(int sock)
{
char *hello = "Hello from client";
char * buffer[1024] = {0};
int valread;
printf("Client sock id: %d\n", sock);
sleep(2);
/* Connection to the server will be handled here */
send(sock , hello , strlen(hello) , 0 );
printf("Hello message sent\n");
valread = read( sock , buffer, 1024);
printf("%s\n",buffer );
close(sock);
}
int main(int argc, char const *argv[])
{
struct sockaddr_in address;
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERVER_PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
record_video();
handle_request(sock);
return 0;
}
I'm trying to implement communication by UDP protocol, and I'm getting an error: "Error sending: Address family not supported by protocol". I've checked in Google for this problem but couldn't managed to find answer.
Please be patient, I'm only starting my adventure with coding in C.
Here is a C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUFLEN 512
// define function that deals with errors
void error(const char *msg)
{
perror(msg); // print error msg
exit(1); // exit the main() function
}
int main(int argc, char *argv[])
{
struct sockaddr_in serv1_addr, serv2_addr, cli1_addr, cli2_addr; //definicja struktur adresów servera i clienta
struct hostent *server; //defines host addres struct
int cl1_sockfd, se1_sockfd, se2_sockfd, i, c1len = sizeof(cli1_addr), c2len = sizeof(cli2_addr), recv_len, portno1,portno2; // creates inits
int cli1_len = sizeof(cli1_addr);
int cli2_len = sizeof(cli2_addr);
char buf[BUFLEN];
if (argc < 4) {
fprintf(stderr,"ERROR, no port provided\n"); // deal with wrong port
exit(1);
}
//tworzenie soceketu servera
if ((se1_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
error("socket1"); //if socket() return -1 -- error
}
if ((se2_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
error("socket2"); //if socket() return -1 -- error
}
//zero out the structure
memset( &serv1_addr, 0, sizeof(serv1_addr)); //put zero into structure
memset( &serv2_addr, 0, sizeof(serv2_addr)); //put zero into structure
portno1 = atoi(argv[2]); // get port number
portno2 = atoi(argv[3]);
serv1_addr.sin_family = AF_INET; // specify address family (IPv4)
serv1_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv1_addr.sin_port = htons(portno1); // set port number
serv2_addr.sin_family = AF_INET; // specify address family (IPv4)
serv2_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv2_addr.sin_port = htons(portno2); // set port number
if(connect(se1_sockfd,(struct sockaddr *) &serv1_addr, sizeof(serv1_addr)) < 0)
error ("ERROR connecting1"); //if connection failed
if(connect(se2_sockfd,(struct sockaddr *) &serv2_addr, sizeof(serv2_addr)) < 0)
error ("ERROR connecting2"); //if connection failed
while(1) //inf loop
{
printf("Please enter the message: "); //write the msg to socket
bzero(buf, 512); //fill buffer with zeros
fgets(buf, 512, stdin); //read into buffer
if( sendto( se1_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli1_addr, cli1_len) < 0)
error ("Error sending1");
if( sendto( se2_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli2_addr, cli2_len) < 0)
error ("Error sending2");
if (recvfrom(se1_sockfd, buf, BUFLEN, 0, (struct sockaddr *) &cli1_addr, &cli1_len) == -1){
error("recivfrom()1"); //if reciving failed -- error
}
printf("Data: %s\n", buf);
if (recvfrom(se2_sockfd, buf, BUFLEN, 0, (struct sockaddr *) &cli2_addr, &cli2_len) == -1){
error("recivfrom()2"); //if reciving failed -- error
}
printf("Data: %s\n", buf);
}
close(se1_sockfd);
close(se2_sockfd);
return 0;
}
Thanks for your help. ;)
Your issue is likely because of uninitialized destination address. sendto() takes destination address as the one before the last argument. But you are trying to provide not-initialized address (like for recvfrom())
if( sendto( se1_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli1_addr, cli1_len) < 0)
error ("Error sending1");
^^^
Try serv1_addr instead ?
Also need to provide appropriate size.
One more thing. As long as you use sendto() - no need to perform connect(). UDP is connectionless and connect() only establishes default destination address for those who is going to use send() on such socket. But this is not your case because you provide destination address each time you call sendto(). Even more - you may use different addresses each time.
P.S. Reference: sendto()
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){
I am working through examples in UNIX Network Programming and I've adapted "daytimeclientserv.c" into this code here. The server sends the date/time string to the client as expected except for the very first request it receives upon starting up. When I first run the server program (on another computer in the LAN) it creates the listening socket, binds it and then waits for connections. Upon receiving the first request it prints the date/time string to its own stdout (terminal) instead of to the socket and the client program hangs forever waiting. However, all subsequent requests are sent to the clients correctly. Using gdb, I noticed that connfd is always set to zero. It is set to zero on the first request and also on all future ones.
I also have a few other questions related to this:
if the server listens on one socket (listenfd) and then reconnects on another (connfd) with connect(), how does the client deal with the change of socket? It was my understanding that a socket is uniquely identified by four parts: servIPaddr, servPort, clientIPaddr, clientPort
how can i run the server (on linux) without being root
how can i cleanly close the listening socket, so that i can use it again. I get a bind error if I quit the server program with SIGINT (Ctrl-C). So far I've been using gdb, and using a "call close(listenfd)" to manually call the function. But is there a way to do this if I am not using gdb (ie. debugging the client application only).
Any help is greatly appreciated.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#define BUFFER 80
int main(int argc, char **argv) {
int listenfd, connfd;
char buf[BUFFER];
struct sockaddr_in servaddr;
time_t ticks;
struct sockaddr *ptr;
char *ret;
if ( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket error");
return 1;
}
memset(&servaddr, 0, sizeof(servaddr));
memset(buf, 0, BUFFER);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(13);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
ptr = (struct sockaddr*) &servaddr;
if ( bind(listenfd, ptr ,sizeof(servaddr)) < 0) {
perror("bind error");
return 2;
}
if ( listen(listenfd, 128) < 0) {
perror("listen error");
return 3;
}
ptr = NULL;
while ( 1 ) {
if ( connfd = accept(listenfd, ptr, NULL) < 0) {
perror("accept error");
return 4;
} else {
ticks = time(NULL);
ret = ctime(&ticks);
sprintf(buf, "%.24s\n", ret);
if ( write(connfd, buf, strlen(buf)) < 0) {
perror("write error");
close(connfd);
}
}
return 0;
}
Here was my hunch: On a terminal (tty), stdout and stdin are the same physical device. Therefore writing to filedescriptor 0 (stdin) might actually work and result in terminal output.
You need parentheses around this
if ( connfd = accept(listenfd, ptr, NULL) < 0) {
Like so
if ( (connfd = accept(listenfd, ptr, NULL)) < 0) {
Or connfd will be assigned '0'
Update Just tested this, and this is indeed the culprit. Next time, compile with gcc -Wall and the compiler would have told you this (and several other issues of good form/style). That way, you won't have to rely on having the hunch to find the error.
Fixed version:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#define BUFFER 80
int main(int argc, char **argv) {
int listenfd, connfd;
char buf[BUFFER];
struct sockaddr_in servaddr;
time_t ticks;
struct sockaddr *ptr;
char *ret;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if ( listenfd < 0 ) {
perror("socket error");
return 1;
}
memset(&servaddr, 0, sizeof(servaddr));
memset(buf, 0, BUFFER);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(13);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
ptr = (struct sockaddr*) &servaddr;
if ( bind(listenfd, ptr ,sizeof(servaddr) ) < 0) {
perror("bind error");
return 2;
}
if ( listen(listenfd, 128) < 0 ) {
perror("listen error");
return 3;
}
ptr = NULL;
while ( 1 ) {
connfd = accept(listenfd, ptr, NULL);
if ( connfd < 0 ) {
perror("accept error");
return 4;
} else {
ticks = time(NULL);
ret = ctime(&ticks);
sprintf(buf, "%.24s\n", ret);
if ( write(connfd, buf, strlen(buf)) < 0) {
perror("write error");
close(connfd);
}
}
}
return 0;
}