Linux_C socket 数据报之client, server.c
dgrecv.c
1 /**************************************************************** 2 * dgrecv.c - datagram receiver 3 * usage: dgrecv portnum 4 * action: listens at the specfied port and reports messages 5 */ 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <sys/types.h> 9 #include <sys/socket.h> 10 #include <netinet/in.h> 11 #include <netdb.h> 12 #include <string.h> 13 #include <arpa/inet.h> 14 #include <unistd.h> 15 16 #define oops(m,x) {perror(m); exit(x);} 17 18 int make_dgram_server_socket(int); 19 int get_internet_address(char* , int , int *, struct sockaddr_in *); 20 void say_who_called(struct sockaddr_in* ); 21 22 int main(int argc, char* argv[]) { 23 int port; 24 int sock; 25 char buf[BUFSIZ]; 26 size_t msglen; 27 struct sockaddr_in saddr; 28 socklen_t saddrlen; 29 30 if(argc==1 || (port=atoi(argv[1]))<=0){ 31 fprintf(stderr, "usage :dgrecv portnumber\n"); 32 exit(1); 33 } 34 35 /*get a socket and assign it a port number*/ 36 if((sock=make_dgram_server_socket(port))==-1) 37 oops("cannot make server", 2); 38 39 /*receive messages on that socket*/ 40 saddrlen=sizeof(saddr); 41 while((msglen=recvfrom(sock ,buf, BUFSIZ, 0, &saddr, &saddrlen))>0) { 42 buf[msglen]='\0'; 43 printf("dgrecv: got a message: %s\n", buf); 44 say_who_called(&saddr); 45 } 46 return 0; 47 } 48 49 //return the sock_id 50 int make_dgram_server_socket(int port){ 51 struct sockaddr_in saddr; 52 struct hostent *hp; 53 char hostname[BUFSIZ]; 54 int sock; 55 56 sock=socket(PF_INET, SOCK_DGRAM, 0); 57 if(sock==-1) 58 return -1; 59 gethostname(hostname, BUFSIZ); 60 hp=gethostbyname(hostname); 61 bzero((void*)&saddr, sizeof(saddr)); 62 bcopy(hp->h_addr, (struct sockaddr*)&saddr.sin_addr, hp->h_length); 63 saddr.sin_family=AF_INET; 64 saddr.sin_port=htons(port); 65 if(bind(sock, (struct sockaddr*)&saddr, sizeof(saddr))!=0) 66 return -1; 67 return sock; 68 } 69 70 int get_internet_address(char* host, int len, int *portp, struct sockaddr_in* addrp) { 71 /* 72 * extracts host and port from an internet socket address 73 * *addrp->(host, port) 74 */ 75 strncpy(host, inet_ntoa(addrp->sin_addr), len); 76 *portp=ntohs(addrp->sin_port); 77 return 0; 78 } 79 80 void say_who_called(struct sockaddr_in *addrp) { 81 char host[BUFSIZ]; 82 int port; 83 84 get_internet_address(host, BUFSIZ, &port, addrp); 85 printf("from: %s: %d\n", host, port); 86 }
dgsend.c
1 /*********************************************************************** 2 * dgsend.c - datagram sender 3 * usage: dgsend hostname portnumber "message" 4 * action: sends message to hostname : portnumber 5 */ 6 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <sys/types.h> 10 #include <sys/socket.h> 11 #include <netinet/in.h> 12 #include <netdb.h> 13 14 #define oops(m, x) {perror(m); exit(x);} 15 16 int main(int argc, char* argv[]) { 17 char *message; 18 int cli_sock; 19 struct sockaddr_in saddr; 20 struct hostent *hp; 21 22 if(argc!=4){ 23 printf("please cin hostname portnumber and message ./n"); 24 exit(-1); 25 } 26 cli_sock=socket(AF_INET, SOCK_DGRAM, 0); 27 if(cli_sock==-1) 28 oops("cannot make socket", 2); 29 30 message=argv[3]; 31 32 /*make internet address*/ 33 bzero((void*)&saddr, sizeof(saddr)); 34 hp=gethostbyname(argv[1]); 35 bcopy(hp->h_addr, (struct sockaddr*)&saddr.sin_addr, hp->h_length); 36 saddr.sin_family=AF_INET; 37 saddr.sin_port=htons(atoi(argv[2])); 38 39 if(sendto(cli_sock, message, strlen(message), 0, &saddr, sizeof(saddr))==-1) 40 oops("sendto failed", 3); 41 return 0; 42 }
其中,注意
为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。
#include <arpa/inet.h>
uint32_t
uint16_t
uint32_t
uint16_t
htonl(uint32_t
htons(uint16_t
ntohl(uint32_t
ntohs(uint16_t
hostlong);
hostshort);
netlong);
netshort);
这些函数名很好记,h表示host,n表示network,l表示32位长整数,s表示16位短整数。例
如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。如果
主机是小端字节序,这些函数将参数做相应的大小端转换然后返回,如果主机是大端字节序,这些
函数不做转换,将参数原封不动地返回。
posted on 2014-11-17 21:24 Zachary_wiz 阅读(373) 评论(0) 编辑 收藏 举报