1. 简单的数据报编程
dgrecv.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define oops(m,x) {perror(m);exit(x);}
int make_dgram_server_socket( int );
int get_internet_address( char *, int, int *, struct sockaddr_in * );
void say_who_called( struct sockaddr_in * );
void reply_to_sender( int, char *, struct sockaddr_in *, socklen_t );
int main( int ac, char *av[] )
{
int port;
int sock;
char buf[ BUFSIZ ];
size_t msglen;
struct sockaddr_in saddr;
socklen_t saddrlen;
if ( ac == 1 || ( port = atoi( av[ 1 ] ) ) <= 0 ){
fprintf(stderr, "usage:dgrecv portnumber\n");
exit( 1 );
}
if ( ( sock = make_dgram_server_socket( port ) ) == -1 )
oops("cannot make socket", 2);
saddrlen = sizeof( saddr );
while ( ( msglen = recvfrom( sock, buf, BUFSIZ, 0, &saddr, &saddrlen ) ) > 0 ){
buf[ msglen ] = '\0';
printf("dgrecv:got a message:%s\n", buf);
say_who_called(&saddr);
reply_to_sender(sock, buf, &saddr, saddrlen);
}
return 0;
}
void reply_to_sender( int sock, char *msg, struct sockaddr_in *addrp, socklen_t len )
{
char reply[ BUFSIZ + BUFSIZ ];
sprintf(reply, "thanks for your %d char message\n", strlen( msg ) );
sendto( sock, reply, strlen( reply ), 0, addrp, len );
}
void say_who_called( struct sockaddr_in *addrp )
{
char host[ BUFSIZ ];
int port;
get_internet_address( host, BUFSIZ, &port, addrp );
printf("from:%s:%d\n", host, port );
}
dgsend.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define oops(m,x) {perror(m);exit(x);}
int make_dgram_client();
int make_internet_address( char *, int, struct sockaddr_in * );
int main( int ac, char *av[] )
{
int sock;
char *msg;
struct sockaddr_in saddr;
if ( ac != 4 ){
fprintf( stderr, "usage:dgsend host port message\n");
exit( 1 );
}
msg = av[ 3 ];
if ( ( sock = make_dgram_client_socket() ) == -1 )
oops("cannot make socket", 2);
make_internet_address( av[ 1 ], atoi( av[ 2 ] ), &saddr );
if ( sendto( sock, msg, strlen( msg ), 0, &saddr, sizeof( saddr ) ) == -1 )
oops("sendto failed", 3);
return 0;
}
dgram.c:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#define HOSTLEN 256
int make_internet_address( char *hostname, int port, struct sockaddr_in *addrp );
int make_dgram_server_socket( int portnum )
{
struct sockaddr_in saddr;
char hostname[ HOSTLEN ];
int sock_id;
sock_id = socket( PF_INET, SOCK_DGRAM, 0 );
if ( sock_id == -1 )
return -1;
gethostname( hostname, HOSTLEN );
make_internet_address( hostname, portnum, &saddr );
if ( bind( sock_id, ( struct sockaddr *)&saddr, sizeof( saddr ) ) != 0 )
return -1;
return sock_id;
}
int make_dgram_client_socket()
{
return socket( PF_INET, SOCK_DGRAM, 0 );
}
int make_internet_address( char *hostname, int port, struct sockaddr_in *addrp )
{
struct hostent *hp;
bzero( ( void * )addrp, sizeof( struct sockaddr_in ) );
hp = gethostbyname( hostname );
if ( hp == NULL ) return -1;
bcopy( ( void * )hp->h_addr, ( void * )&addrp->sin_addr, hp->h_length );
addrp->sin_port = htons( port );
addrp->sin_family = AF_INET;
return 0;
}
int get_internet_address( char *host, int len, int *portp, struct sockaddr_in *addrp )
{
strncpy( host, inet_ntoa( addrp->sin_addr), len );
*portp = ntohs( addrp->sin_port);
return 0;
}
程序运行结果:
leichaojian@ThinkPad-T430i:~$ cc dgrecv.c dgram.c -o dgrecv
leichaojian@ThinkPad-T430i:~$ ./dgrecv 4444 &
[1] 12875
leichaojian@ThinkPad-T430i:~$ cc dgsend.c dgram.c -o dgsend
leichaojian@ThinkPad-T430i:~$ ./dgsend ThinkPad-T430i 4444 "this is a test"
dgrecv:got a message:this is a test
from:127.0.0.1:41776
leichaojian@ThinkPad-T430i:~$ ps
PID TTY TIME CMD
7350 pts/1 00:00:00 bash
12875 pts/1 00:00:00 dgrecv
12887 pts/1 00:00:00 ps