实现一个基于UDP的应用
UDP的所调用的函数和用于TCP的函数非常类似。这主要因为套接口库在底层的TCP和UDP函数上加了一层抽象。
在使用TCP和使用UDP之间,函数调用的惟一实际区别在于socket函数调用的一个参数。这个参数为SOCK_STREAM时代表TCP,而SOCK_DGRAM代表UDP。
使用UDP发送数据
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int port = 6789;
void main() {
int socket_descriptor;
int iter = 0;
char buf[80];
struct sockaddr_in address;
/* Initialize socket address structure for Internet Protocols*/
bzero(&address, sizeof(address)); /* empty data structure */
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(port);
/* Create a UDP socket*/
socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
/* Loop 20 times (a nice round number) sending data.*/
for (iter = 0; iter <= 20; iter++)
{
sprintf(buf,"data packet with ID %d\n", iter);
sendto(socket_descriptor,
buf, sizeof(buf),
0, (struct sockaddr *)&address, sizeof(address));
}
/* Send a termination message*/
sprintf(buf, "stop\n");
sendto(socket_descriptor,
buf, sizeof(buf),
0, (struct sockaddr *)&address, sizeof(address));
close(socket_descriptor);
printf("Messages Sent, Terminating\n");
exit (0);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int port = 6789;
void main() {
int sin_len;
char message[256];
int socket_descriptor;
struct sockaddr_in sin;
printf("Waiting for data from sender\n");
/* Initialize socket address structure for Internet Protocols*/
bzero(&sin, sizeof(sin)); /* empty data structure */
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(port);
sin_len = sizeof(sin);
/*
Create a UDP socket
and bind it to the port
*/
socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
bind(socket_descriptor, (struct sockaddr *)&sin, sizeof(sin));
/*
Loop forever (or until a termination message is received)
Receive data through the socket and process it. The processing
in this program is really simple -- printing.
*/
while (1)
{
recvfrom(socket_descriptor, message, sizeof(message), 0,
(struct sockaddr *)&sin, &sin_len);
printf("Response from server: %s\n", message);
if (strncmp(message, "stop", 4) == 0)
{
printf("Sender has told me to end the connection\n");
break;
}
}
close(socket_descriptor);
exit (0);
}
--- sender.c 2000-09-22 20:51:26.000000000 +0800
+++ sender2.c 2000-09-22 20:51:26.000000000 +0800
@@ -5,45 +5,83 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
+#include <errno.h>
int port = 6789;
void main() {
int socket_descriptor;
int iter = 0;
+ ssize_t sendto_rc;
+ int close_rc;
char buf[80];
struct sockaddr_in address;
+ struct hostent *hostbyname;
/*
+ Translate a host name to IP address
+*/
+ hostbyname = gethostbyname("127.0.0.1");
+ if (hostbyname == NULL)
+ {
+ perror ("gethostbyname failed");
+ exit (errno);
+ }
+/*
Initialize socket address structure for Internet Protocols
+ The address comes from the datastructure returned by gethostbyname()
*/
bzero(&address, sizeof(address)); /* empty data structure */
address.sin_family = AF_INET;
- address.sin_addr.s_addr = inet_addr("127.0.0.1");
+ memcpy(&address.sin_addr.s_addr, hostbyname->h_addr, sizeof(address.sin_addr.s_addr));
address.sin_port = htons(port);
/*
Create a UDP socket
*/
socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
+ if (socket_descriptor == -1)
+ {
+ perror ("socket call failed");
+ exit (errno);
+ }
/*
Loop 20 times (a nice round number) sending data.
*/
for (iter = 0; iter <= 20; iter++)
{
sprintf(buf,"data packet with ID %d\n", iter);
- sendto(socket_descriptor,
+ sendto_rc = sendto(socket_descriptor,
buf, sizeof(buf),
0, (struct sockaddr *)&address, sizeof(address));
+ if (sendto_rc == -1)
+ {
+ perror ("sendto call failed");
+ exit (errno);
+ }
}
/*
Send a termination message
*/
sprintf(buf, "stop\n");
- sendto(socket_descriptor,
+ sendto_rc = sendto(socket_descriptor,
buf, sizeof(buf),
0, (struct sockaddr *)&address, sizeof(address));
+ if (sendto_rc == -1)
+ {
+ perror ("sendto STOP call failed");
+ exit (errno);
+ }
+/*
+ Most people don't bother to check the return code
+ returned by the close function
+*/
+ close_rc = close(socket_descriptor);
+ if (close_rc == -1)
+ {
+ perror ("close call failed");
+ exit (errno);
+ }
- close(socket_descriptor);
printf("Messages Sent, Terminating\n");
exit (0);
}
--- receiver.c 2000-09-22 20:51:26.000000000 +0800
+++ receiver2.c 2000-09-22 20:51:26.000000000 +0800
@@ -5,6 +5,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
+#include <errno.h>
int port = 6789;
@@ -13,6 +14,9 @@
char message[256];
int socket_descriptor;
struct sockaddr_in sin;
+ int bind_rc, close_rc;
+ ssize_t recv_rc;
+
printf("Waiting for data from sender\n");
/*
Initialize socket address structure for Internet Protocols
@@ -27,7 +31,18 @@
and bind it to the port
*/
socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
- bind(socket_descriptor, (struct sockaddr *)&sin, sizeof(sin));
+ if (socket_descriptor == -1)
+ {
+ perror ("socket call failed");
+ exit (errno);
+ }
+
+ bind_rc = bind(socket_descriptor, (struct sockaddr *)&sin, sizeof(sin));
+ if (bind_rc == -1)
+ {
+ perror ("bind call failed");
+ exit (errno);
+ }
/*
Loop forever (or until a termination message is received)
Receive data through the socket and process it. The processing
@@ -35,16 +50,33 @@
*/
while (1)
{
- recvfrom(socket_descriptor, message, sizeof(message), 0,
+ recv_rc = recvfrom(socket_descriptor, message, sizeof(message), 0,
(struct sockaddr *)&sin, &sin_len);
+ if (recv_rc == -1)
+ {
+ perror ("recvfrom call failed");
+ exit (errno);
+ }
+
printf("Response from server: %s\n", message);
+
if (strncmp(message, "stop", 4) == 0)
{
printf("Sender has told me to end the connection\n");
break;
}
}
- close(socket_descriptor);
+/*
+ Most people don't bother to check the return code
+ returned by the close function
+*/
+ close_rc = close(socket_descriptor);
+ if (close_rc == -1)
+ {
+ perror ("close call failed");
+ exit (errno);
+ }
+
exit (0);
}
--- sender2.c 2000-09-22 20:51:26.000000000 +0800
+++ sender3.c 2000-09-22 20:51:26.000000000 +0800
@@ -58,7 +58,10 @@
perror ("sendto call failed");
exit (errno);
}
+ sleep(3); /* this is the only difference from sender2.c */
}
+
+
/*
Send a termination message
*/
--- receiver2.c 2000-09-22 20:51:26.000000000 +0800
+++ receiver3.c 2000-09-22 20:51:26.000000000 +0800
@@ -6,6 +6,7 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
+#include <fcntl.h>
int port = 6789;
@@ -16,6 +17,7 @@
struct sockaddr_in sin;
int bind_rc, close_rc;
ssize_t recv_rc;
+ long save_file_flags;
printf("Waiting for data from sender\n");
/*
@@ -44,20 +46,41 @@
exit (errno);
}
/*
+ set socket to non-blocking:
+*/
+ save_file_flags = fcntl(socket_descriptor, F_GETFL);
+ printf("file flags are %ld\n", save_file_flags);
+ save_file_flags |= O_NONBLOCK;
+ if (fcntl(socket_descriptor, F_SETFL, save_file_flags) == -1)
+ {
+ perror("trying to set input socket to non-blocking");
+ exit (errno);
+ }
+ printf("file flags are now %ld\n", save_file_flags);
+
+/*
Loop forever (or until a termination message is received)
Receive data through the socket and process it. The processing
in this program is really simple -- printing.
*/
while (1)
{
+ sleep (1); /* wait a moment... */
recv_rc = recvfrom(socket_descriptor, message, sizeof(message), 0,
(struct sockaddr *)&sin, &sin_len);
- if (recv_rc == -1)
+ if (recv_rc == -1 && errno != EAGAIN)
{
- perror ("recvfrom call failed");
+ fprintf(stderr, "errno %d ", errno); perror ("recvfrom call failed");
exit (errno);
}
+ else if (recv_rc == 0 || errno == EAGAIN) /* no data */
+ {
+ printf("no data yet\n");
+ errno = 0; /* clear the error */
+ continue;
+ }
+ errno = 0; /* clear the error */
printf("Response from server: %s\n", message);
if (strncmp(message, "stop", 4) == 0)
文章评论(0条评论)
登录后参与讨论