C/S模型-UDP
在创建socket时,若将socket()函数中的参数type设置为SOCK_DGRAM,程序将采用UDP传输协议,以数据包的形式传输数据。
案例2:编写C/S模式的程序,分别创建服务器和客户端。客户端的功能是从终端获取一个字符串发送给服务器,然后接收服务器返回的字符串并打印;服务器的功能是从客户端发来的字符,将每个字符转换为大写再返回给客户端。案例实现如下。
udpserver.c //服务器端
1 #include <string.h>
2 #include <netinet/in.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <strings.h>
6 #include <arpa/inet.h>
7 #include <ctype.h>
8 #define MAXLINE 80 //最大连接数
9 #define SERV_PORT 6666 //服务器端口号
10 int main(void)
11 {
12 struct sockaddr_in servaddr, cliaddr; //定义服务器与客户端地址结构体
13 socklen_t cliaddr_len; //客户端地址长度
14 int sockfd; //服务器socket文件描述符
15 char buf[MAXLINE];
16 char str[INET_ADDRSTRLEN];
17 int i, n;
18 sockfd = socket(AF_INET, SOCK_DGRAM, 0);//创建服务器端套接字文件
19 //初始化服务器端口地址
20 bzero(&servaddr, sizeof(servaddr)); //地址结构体清零
21 servaddr.sin_family = AF_INET; //指定协议族
22 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
23 servaddr.sin_port = htons(SERV_PORT); //指定端口号
24 //绑定服务器端口地址
25 bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
26 printf("Accepting connections ...\n");
27 //数据传输
28 while (1) {
29 cliaddr_len = sizeof(cliaddr);
30 //接收数据
31 n=recvfrom(sockfd,buf,MAXLINE,0,(struct sockaddr*)&cliaddr,
32 &cliaddr_len);
33 if (n == -1)
34 perror("recvfrom error");
35 printf("received from %s at PORT %d\n",
36 inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
37 ntohs(cliaddr.sin_port));
38 //服务器端操作,小写转大写
39 for (i = 0; i < n; i++)
40 buf[i] = toupper(buf[i]);
41 n =sendto(sockfd, buf,n,0,(struct sockaddr *)&cliaddr,
42 sizeof(cliaddr));
43 if (n == -1)
44 perror("sendto error");
45 }
46 close(sockfd);
47 return 0;
48 }
udpclient.c //客户端
1 #include <stdio.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <netinet/in.h>
5 #include <arpa/inet.h>
6 #include <strings.h>
7 #include <ctype.h>
8 #define MAXLINE 80
9 #define SERV_PORT 6666
10 int main(int argc, char *argv[])
11 {
12 struct sockaddr_in servaddr;
13 int sockfd, n;
14 char buf[MAXLINE];
15 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
16 bzero(&servaddr, sizeof(servaddr));
17 servaddr.sin_family = AF_INET;
18 inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
19 servaddr.sin_port = htons(SERV_PORT);
20 //发送数据到客户端
21 while (fgets(buf, MAXLINE, stdin) != NULL) {
22 n =sendto(sockfd, buf, strlen(buf),0,(struct sockaddr *)&servaddr,
23 sizeof(servaddr));
24 if (n == -1)
25 perror("sendto error");
26 //接收客户端返回的数据
27 n = recvfrom(sockfd, buf, MAXLINE, 0, NULL, 0);
28 if (n == -1)
29 perror("recvfrom error");
30 //将接收到的数据打印到终端
31 send(STDOUT_FILENO, buf, n,0);
32 }
33 close(sockfd);
34 return 0;
35 }
编译以上两端代码,打开两个终端窗口,先执行服务器端程序,再执行客户端程序,同时输入需要转换的字符串,服务器端和客户端对应的终端中分别打印如下信息:
服务器端:
Accepting connections ...
received from 127.0.0.1 at PORT 33059
received from 127.0.0.1 at PORT 33059
客户机端:
hello
HELLO
world
WORLD
由程序执行结果可知,服务器成功换成客户端发来的字符串转,案例实现成功。