unix網絡編程代碼(4)

繼續貼《unix網絡編程》上的示例代碼。在上一篇帖子中的反射程序使用了tcp協議實現,此次使用udp協議實現。linux

server段代碼:編程

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <unistd.h>
 5 #include <arpa/inet.h>
 6 #include <sys/socket.h>
 7 #include <sys/types.h>
 8 #include <errno.h>
 9 #include <signal.h>
10 
11 #define SER_PORT 9374
12 
13 void dg_echo (int sockfd,struct sockaddr* pcli,socklen_t clilen);
14 void recvform_int (int signo);
15 
16 int main ()
17 {
18     int sockfd;
19     struct sockaddr_in seraddr,cliaddr;
20     struct sigaction act;   
21     if ((sockfd = socket (AF_INET,SOCK_DGRAM,0)) < 0) {
22         perror ("socket");
23         exit (1);
24     }
25     bzero (&act,sizeof (act));
26     bzero (&seraddr,sizeof (seraddr));
27     bzero (&cliaddr,sizeof (cliaddr));
28     seraddr.sin_family = AF_INET;
29     seraddr.sin_port = htons (SER_PORT);
30     seraddr.sin_addr.s_addr = htonl (INADDR_ANY);
31 
32     if ((bind (sockfd,(struct sockaddr *)&seraddr,sizeof (seraddr))) < 0) {
33         perror ("bind");
34         exit (1);
35     }
36 
37     act.sa_handler = recvform_int;
38     sigemptyset (&act.sa_mask);
39     act.sa_flags = 0;
40 
41     if ((sigaction (SIGINT,&act,NULL)) < 0) {
42         perror ("sigaction");
43         exit (1);
44     }
45 
46     dg_echo (sockfd,(struct sockaddr*) &cliaddr,sizeof (cliaddr));
47     
48     return 0;
49 }
50 
51 void recvform_int (int signo)
52 {
53     printf ("terminated by user\n");
54     exit (1);
55 }
56 
57 void dg_echo (int sockfd,struct sockaddr* pcli,socklen_t clilen)
58 {
59     int n;
60     char recvline[4096];
61     socklen_t len = clilen;
62 
63     while (1) {
64         len = clilen;
65         n = recvfrom (sockfd,recvline,4096,0,pcli,&len);
66         sendto (sockfd,recvline,n,0,pcli,len);
67     }
68 }
69 
70     

 

client端代碼: 1 #include <stdlib.h>服務器

 2 #include <stdio.h>
 3 #include <unistd.h>
 4 #include <errno.h>
 5 #include <arpa/inet.h>
 6 #include <netinet/in.h>
 7 #include <sys/socket.h>
 8 #include <sys/types.h>
 9 #include <string.h>
10 
11 #define SER_PORT 9374
12 
13 void dg_cli (FILE *fp,int sockfd, 14         const struct sockaddr *pser, 15  socklen_t serlen); 16 
17 int main () 18 { 19     int sockfd; 20     struct sockaddr_in seraddr; 21     char *ip = "127.0.0.1"; 22 
23     if ((sockfd = socket (AF_INET,SOCK_DGRAM,0)) == -1) { 24         perror ("socket"); 25         exit (1); 26  } 27 
28     bzero (&seraddr,sizeof (seraddr)); 29     seraddr.sin_family = AF_INET; 30     seraddr.sin_port = htons (SER_PORT); 31     inet_pton (AF_INET,ip,&seraddr.sin_addr); 32 
33     dg_cli (stdin,sockfd,(struct sockaddr*)&seraddr,sizeof (seraddr)); 34 
35     return 0; 36 } 37 
38 
39 void dg_cli (FILE *fp,int sockfd, 40         const struct sockaddr *pser, 41  socklen_t serlen) { 42     int n; 43     char sendline[4096]; 44     char recvline[4096];
45 if ((connect (sockfd,pser,serlen)) < 0) { 46 perror ("connect"); 47 exit (1); 48 } 49 50 while ((fgets (sendline,4096,fp)) != NULL) { 51 write (sockfd,sendline,strlen (sendline)); 52 n = read (sockfd,recvline,4096); 53 recvline[n] = '\0'; 54 printf ("%s\n",recvline); 55 } 56 }

在客戶端中,按下鍵盤ctrl+c輸入EOF,fgets函數會自動退出;在服務端中按下ctrl+c結束程序(由於設置捕捉了SIGINT信號)。網絡

在客戶端中使用了connect函數(是的,在udp協議中也能夠使用connect函數),《unix網絡編程》對於connect函數有以下總結:socket

咱們能夠說UDP客戶進程或者服務進程只在使用本身的UDP套接字與肯定的惟一對端進行通信,纔會調用connect。調用connect的一般是UDP客戶,不過某些網絡應用中的UDP服務器會與單個客戶長時間通訊(好比TFTP),這種狀況下,客戶和服務都有可能調用connect。在linux programmer`s manual手冊中,關於connect和udp是這麼說的:tcp

If the socket sockfd is of type SOCK_DGRAM, then addr is the address to
which datagrams are sent by default, and the only address from which
datagrams are received.函數

例如:connect  (sockfd,(struct sockaddr*)addr,sizeof (addr));spa

若是sockfd是使用UDP的一個套接字,那麼addr所表示的地址就是使用sockfd文件描述符發送數據的默認地址(默認發送到addr所示的地址),以及使用sockfd可以接收到的數據的惟一來源。unix

相關文章
相關標籤/搜索