Professional Documents
Culture Documents
The example featured in this section consists of two applications: a client and a server.
The server continuously receives datagram packets over a datagram socket. Each
datagram packet received by the server indicates a client request for a quotation. When
the server receives a datagram, it replies by sending a datagram packet that contains a
one-line "quote of the moment" back to the client.
The client application in this example is fairly simple. It sends a single datagram packet
to the server indicating that the client would like to receive a quote of the moment. The
client then waits for the server to send a datagram packet in response.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <pthread.h>
#include <syslog.h>
#include <unistd.h>
typedef enum
{
false,
true
} bool;
struct message
{
long message_id;
char buffer[MAX_MESSAGE_SIZE];
};
if (pthread_attr_init(&thread_attr) != 0)
error("pthread_attr_init");
if (pthread_attr_setdetachstate(&thread_attr,
PTHREAD_CREATE_DETACHED) != 0)
error("pthread_attr_setdetachstate");
time_t now;
srand(seed);
if (close(sock_fd) == -1)
error("close");
}
if (rptr == NULL)
{ // Not successful with any address
fprintf(stderr, "Not able to bind\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(result);
while (1)
{
addrlen = sizeof(struct sockaddr_storage);
// lock mutex
if ((r = pthread_mutex_lock(&client_mutex)) != 0)
{
fprintf(stderr, "Error = %d (%s)\n", r,
strerror(r));
exit(1);
}
// Unlock mutex
if ((r = pthread_mutex_unlock(&client_mutex)) != 0)
{
fprintf(stderr, "Error = %d (%s)\n", r,
strerror(r));
exit(1);
}
if (i == MAX_CLIENTS)
{
fprintf(stderr, "Can't handle more than %d clients.
Quitting\n", MAX_CLIENTS);
exit(EXIT_FAILURE);
}
if ((clients[i].accepted_sock_id = accept(sock_fd,
(struct sockaddr *)&clients[i].client, &addrlen)) == -1)
{
if (errno == EINTR)
{
// lock mutex
if ((r = pthread_mutex_lock(&client_mutex)) !=
0)
{
fprintf(stderr, "Error = %d (%s)\n", r,
strerror(r));
exit(1);
}
clients[i].is_a_client = false;
// Unlock mutex
if ((r = pthread_mutex_unlock(&client_mutex)) !=
0)
{
fprintf(stderr, "Error = %d (%s)\n", r,
strerror(r));
exit(1);
}
continue;
}
else
{
error("accept");
}
}
exit(EXIT_SUCCESS);
}
i = *((int *)arg);
// lock mutex
if ((r = pthread_mutex_lock(&client_mutex)) != 0)
{
fprintf(stderr, "Error = %d (%s)\n", r, strerror(r));
exit(1);
}
this_client = clients[i];
// Unlock mutex
if ((r = pthread_mutex_unlock(&client_mutex)) != 0)
{
fprintf(stderr, "Error = %d (%s)\n", r, strerror(r));
exit(1);
}
if ((this_client.client).ss_family == AF_INET)
{
ptr = (struct sockaddr_in *)&(this_client.client);
inet_ntop(AF_INET, &(ptr->sin_addr), str, sizeof(str));
}
else if ((this_client.client).ss_family == AF_INET6)
{
ptr1 = (struct sockaddr_in6 *)&(this_client.client);
inet_ntop(AF_INET6, &(ptr1->sin6_addr), str,
sizeof(str));
}
else
{
ptr = NULL;
fprintf(stderr, "Address family is neither AF_INET nor
AF_INET6\n");
}
if (ptr)
syslog(LOG_USER | LOG_INFO, "%s %s", "Connection from
client", str);
// lock mutex
if ((r = pthread_mutex_lock(&client_mutex)) != 0)
{
fprintf(stderr, "Error = %d (%s)\n", r,
strerror(r));
exit(1);
}
clients[i].is_a_client = false;
// Unlock mutex
if ((r = pthread_mutex_unlock(&client_mutex)) != 0)
{
fprintf(stderr, "Error = %d (%s)\n", r,
strerror(r));
exit(1);
}
break;
}
// process
switch (ntohl(recv_message.message_id))
{
case QUOTATION_PLEASE: // choose a quote
send_message.message_id =
htonl(YOUR_QUOTATION_PLEASE);
int i = rand() % num_quotes;
strcpy(send_message.buffer, quote[i]);
size_t msg_len = sizeof(long) + strlen(quote[i]) +
1;
if (send(this_client.accepted_sock_id,
&send_message, msg_len, 0) == -1)
error("send");
break;
case QUIT:
over = true;
// lock mutex
if ((r = pthread_mutex_lock(&client_mutex)) != 0)
{
fprintf(stderr, "Error = %d (%s)\n", r,
strerror(r));
exit(1);
}
clients[i].is_a_client = false;
// Unlock mutex
if ((r = pthread_mutex_unlock(&client_mutex)) != 0)
{
fprintf(stderr, "Error = %d (%s)\n", r,
strerror(r));
exit(1);
}
continue;
}
}
return (NULL);
}
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#define QUOTE_SERVER_PORT "4356"
#define QUOTATION_PLEASE 1
#define YOUR_QUOTATION_PLEASE 2
#define QUIT 0
typedef enum
false,
true
} bool;
int get_option();
struct message
long message_id;
char buffer[MAX_MESSAGE_SIZE];
};
{
if (argc != 2)
exit(EXIT_FAILURE);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int s;
exit(EXIT_FAILURE);
int sock_fd;
socklen_t length;
rptr->ai_protocol);
if (sock_fd == -1)
continue;
if (close(sock_fd) == -1)
error("close");
continue;
break;
if (rptr == NULL)
exit(EXIT_FAILURE);
}
freeaddrinfo(result);
int option;
while (1)
option = get_option();
message.message_id = htonl(option);
error("send");
if (option == QUIT)
break;
error("recv");
// display
if (ntohl(message.message_id) == YOUR_QUOTATION_PLEASE)
printf("\n%s\n\n", message.buffer);
exit(EXIT_SUCCESS);
int get_option()
int option;
while (1)
printf("Get a Quote\n\n");
printf("\tNew Quote\t1\n");
printf("\tQuit\t\t0\n\n");
scanf("%d", &option);
if (option == 0 || option == 1)
return option;
else
}
void error(char *msg)
perror(msg);
exit(1);
Output :