unix/linux编程实践教程:数据报编程

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值