1、 实验目的:在linux系统下进行网络c语言编程,学习并熟悉使用vim编辑器、gcc编译以及gdb调试,了解网络编程的原理,掌握网络编程中常用的函数。
2、 实验内容: 密文通信
实验共有2个部分,一个是服务器程序udp-server.c,另一个是客户机程序udp-client.c。实验基本思想,通信双方可以互发信息,但所发的内容在网络中是以暗文的形式传送的;双发各持有暗明文对照表,当将暗文接受完成后,又自动将暗文转换成明文形式显示在屏幕上,从而实现了双方间简单的秘密通信,信息传输过程中,即使所发送的数据包被截取,其他人也不能获取准确的信息。
在一个终端中(服务器端)运行 $ ./ server
显示为:
此时,屏幕上首先打印出明文、暗文对照表,服务器正在等待连接请求。
在另一个终端(客户端)运行 $ ./client localhost
显示为:
同样,屏幕上首先打印出明文、暗文对照表,并显示就绪。
服务器端上显示:
服务器端连接成功,可以开始聊天通信。
(1)服务器端发送消息 客户端接收消息
(2)客户端发送消息 服务器端接收消息
3、 源程序及注释
udp-server.c
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/wait.h> #include <unistd.h> #include <arpa/inet.h> #define MAXBUF 1024 #define MYPORT 3490 #define BACKLOG 10 int main(int argc, char **argv) { int sockfd, new_fd; socklen_t len; struct sockaddr_in my_addr, their_addr; char buf[MAXBUF + 1],buf1[MAXBUF+1]; fd_set rfds; struct timeval tv; int retval, maxfd = -1; int i,j,m,n,p,q; //定义并打印明文、暗文对照表 char mid1[]={32,'a','s','d','f','g','h','j','k','l','\n'}; char mid2[]={'0','1','2','3','4','5','6','7','8','9','\n'}; printf("明文、暗文对照表:\n"); for(i=0;i<=10;i++){ printf("%3c",mid1[i]); } for(j=0;j<=11;j++){ printf("%3c",mid2[j]); } //创建一个套接字 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } else printf("socket created\n"); bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT); my_addr.sin_addr.s_addr=INADDR_ANY; bzero(&(my_addr.sin_zero),8); //把自己绑在一个地址上 if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } else printf("binded\n"); //侦听连接 if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } else printf("begin listen\n"); while (1) { len = sizeof(struct sockaddr); //接受引入的请求 if ((new_fd =accept(sockfd, (struct sockaddr *) &their_addr,&len)) == -1) { perror("accept"); continue; } printf("server:got connect from %s\n", inet_ntoa(their_addr.sin_addr)); printf ("\n准备就绪\n"); while(1) { FD_ZERO(&rfds); //清除文件描述符集 FD_SET(0, &rfds); maxfd = 0; FD_SET(new_fd, &rfds); //把当前连接添加到文件描述符集 if (new_fd > maxfd) maxfd = new_fd; //开始等待 tv.tv_sec = 1; tv.tv_usec = 0; retval = select(maxfd + 1, &rfds, NULL, NULL, &tv); if (retval == -1) { printf("将退出,select出错! %s", strerror(errno)); break; } else { if (FD_ISSET(0, &rfds)) { // 读取用户内容发送 bzero(buf, MAXBUF+1); bzero(buf1,MAXBUF+1); fgets(buf, MAXBUF, stdin); //将buf明文转变问buf1暗文发送 for(m=0;m<=strlen(buf);m++) { for(n=0;n<=9;n++) { if(buf[m]==mid1[n]) buf1[m]=mid2[n]; } } len=send(new_fd, buf1, strlen(buf1), 0); if (len > 0) printf ("暗文:%s\t发送成功\n", buf1); else { printf ("暗文:%s\t发送失败\n", buf1); break; } } } if (FD_ISSET(new_fd, &rfds)) { // 接受对方的消息内容 bzero(buf, MAXBUF + 1); bzero(buf1,MAXBUF+1); len=recv(new_fd, buf, MAXBUF, 0); //将buf暗文转变问buf1明文并显示 for(p=0;p<=strlen(buf);p++) { for(q=0;q<=9;q++) { if(buf[p]==mid2[q]) buf1[p]=mid1[q]; } } if (len > 0){ printf ("\n暗文:%s\t接受成功\n", buf); printf("明文:%s\n",buf1); } else { printf ("\n接受失败\n"); break; } } } } close(sockfd); return 0; }
udp-client.c
#include <stdio.h> #include <string.h> #include <errno.h> #include <sys/socket.h> #include <stdlib.h> #include <netinet/in.h> #include <unistd.h> #include <sys/time.h> #include <sys/types.h> #include <netdb.h> #define MAXBUF 1024 #define PORT 3490 int main(int argc, char **argv) { int sockfd; struct hostent *he; struct sockaddr_in their_addr; socklen_t len; char buf[MAXBUF + 1],buf1[MAXBUF+1]; fd_set rfds; struct timeval tv; int retval, maxfd = -1; int i,j,m,n,p,q; if(argc!=2){ fprintf(stderr,"usage:client hostname\n"); exit(1); } //获取主机信息 if((he=gethostbyname(argv[1]))==NULL){ herror("gethostbyname"); exit(1); } //创建一个套接字 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){ perror("socket"); exit(1); } their_addr.sin_family = AF_INET; their_addr.sin_port = htons(PORT); their_addr.sin_addr =* ((struct in_addr *)he->h_addr); bzero(&(their_addr.sin_zero),8); //连接服务器 if (connect(sockfd, (struct sockaddr *) &their_addr, sizeof(their_addr)) == -1) { perror("connect "); exit(1); } //定义并打印明文、暗文对照表 char mid1[]={32,'a','s','d','f','g','h','j','k','l','\n'}; char mid2[]={'0','1','2','3','4','5','6','7','8','9','\n'}; printf("明文、暗文对照表:\n"); for(i=0;i<=10;i++){ printf("%3c",mid1[i]); } for(j=0;j<=11;j++){ printf("%3c",mid2[j]); } printf("准备就绪\n"); while (1) { FD_ZERO(&rfds); //清除文件描述符集 FD_SET(0, &rfds); maxfd = 0; FD_SET(sockfd, &rfds); //把当前连接添加到文件描述符集 if (sockfd > maxfd) maxfd = sockfd; //开始等待 tv.tv_sec = 1; tv.tv_usec = 0; retval = select(maxfd + 1, &rfds, NULL, NULL, &tv); if (retval == -1) { printf("将退出,select出错! %s", strerror(errno)); break; } else { if (FD_ISSET(sockfd, &rfds)) { // 接受对方的消息内容 bzero(buf, MAXBUF + 1); bzero(buf1,MAXBUF+1); len=recv(sockfd, buf, MAXBUF, 0); //将buf暗文转变问buf1明文并显示 for(m=0;m<=strlen(buf);m++) { for(n=0;n<=9;n++) { if(buf[m]==mid2[n]) buf1[m]=mid1[n]; } } if (len > 0){ printf ("\n暗文:%s\t接受成功\n", buf); printf("明文:%s\n",buf1); } else { printf ("\n接受失败\n"); break; } } } if (FD_ISSET(0, &rfds)) { // 读取用户内容发送 bzero(buf, MAXBUF+1); bzero(buf1,MAXBUF+1); fgets(buf, MAXBUF, stdin); //将buf明文转变问buf1暗文发送 for(p=0;p<=strlen(buf);p++) { for(q=0;q<=9;q++) { if(buf[p]==mid1[q]) buf1[p]=mid2[q]; } } len=send(sockfd, buf1, strlen(buf1), 0); if (len > 0) printf ("暗文:%s\t发送成功\n", buf1); else { printf ("暗文:%s\t发送失败\n", buf1); break; } } } close(sockfd); return 0; }