【LINUX/UNIX网络编程】之使用SOCKET进行UDP编程

先看任务需求:

实验二 UDP数据发送与接收

【实验目的】

1、熟练掌握套接字函数的使用方法。

2、应用套接字函数完成基本UDP通讯,实现服务器与客户端的文件传送

【实验学时】

    4学时

【实验内容】

要求:

(1)客户可以从服务器下载文件、或向服务器上传文件。

(2)客户可向服务器发送多种指令:DOWNLOAD、UPLOAD、YES、NO、START、END、SHUTDOWN、CONTENT、OKDOWLOAD格式:DOWLOAD [filename]表示从服务器下载filename文件,如果服务器存在该文件,返回YES,否则返回NO;客户接收如果是YES,可发送START表示开始下载,之后,服务器将文件传送给客户,客户接收并保存;UPLOAD格式:UPLOAD [filename]表示向服务器上传filename文件,服务器发送NO表示拒绝接收。服务器发送START表示开始传送,之后向服务器传输文件;END:表示文件传送结束SHUTDOWN:表示通讯结束,双方退出。

先画一下流程图方便理顺思路:

下面上代码:

1.定义了一个protocol结构体方便传输信息和信息校验等;

 1 #ifndef _protocol
 2 #define _protocol
 3 
 4 #define INFOLEN 1000
 5 #define SHUTDOWN 0
 6 #define DOWNLOAD 1
 7 #define UPLOAD 2
 8 #define YES 3
 9 #define NO 4
10 #define START 5
11 #define END 6
12 #define CONTENT 7
13 #define OK 8
14 
15 struct protocol
16 {
17     int command;
18     int len;  //length of buf
19     int no;
20     char buf[INFOLEN];
21 };
22 #endif

2.客户端程序:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <sys/socket.h>
  5 #include <netinet/in.h>
  6 #include <sys/types.h>
  7 #include <fcntl.h>
  8 #include <sys/stat.h>
  9 #include "protocol.h"
 10 
 11 
 12 /*-----------------------变量声明区------------------*/
 13     int socketfd;
 14     int addrlen;
 15     struct sockaddr_in server;
 16     struct protocol sentbuf;
 17     struct protocol recvbuf;
 18     int num;
 19     char ip[20];
 20     int port;
 21     int choice;
 22     char filename[100];
 23 /*------------------------函数声明区------------------*/
 24 void ShowMenu();
 25 void DownLoad();
 26 void UpLoad();
 27 void ShutDown();
 28 
 29 
 30 int main() {
 31 
 32     /*-------------create UDP socket------------*/
 33     if((socketfd = socket(AF_INET,SOCK_DGRAM,0)) == -1){
 34         perror("socket error\n");
 35         exit(1);
 36     }
 37 
 38     /*-----------------IO-----------------------*/
 39     printf("Please input the ip:\n");
 40     scanf("%s",ip);
 41     printf("Please input the port:\n");
 42     scanf("%d",&port);
 43 
 44     /*--------------------recvfrom and sendto----------*/
 45     bzero(&server,sizeof(server));
 46     server.sin_family = AF_INET;
 47     server.sin_port = htons(port);
 48     server.sin_addr.s_addr = inet_addr(ip);
 49     addrlen = sizeof(server);
 50 
 51     /*--------------------调试信息---------------------------
 52     recvbuf.command = DOWNLOAD;
 53     recvbuf.no =0;
 54     printf("input the message:\n");
 55     scanf("%s",recvbuf.buf);
 56     recvbuf.len = strlen(recvbuf.buf);
 57     sendto(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&server,sizeof(server)); */
 58 
 59 
 60     while (1){
 61     ShowMenu();
 62     scanf("%d",&choice);
 63     if(choice == SHUTDOWN){
 64         ShutDown();
 65         break;
 66     }
 67     else if(choice == DOWNLOAD){
 68         DownLoad();
 69     }
 70     else if(choice == UPLOAD){
 71         UpLoad();
 72     }
 73     else{
 74         printf("Please make a right choice!\n");
 75     }
 76 } 
 77 
 78     /*-----------------close------------------------*/
 79     close(socketfd);
 80     return 0;
 81 }
 82 
 83 
 84 void ShowMenu(){
 85     printf("=====================================\n");
 86     printf("         Please make a choice:       \n");
 87     printf("         0:  ||shutdown||            \n");
 88     printf("         1:  ||download||            \n");
 89     printf("         2:  || upload ||            \n");
 90     printf("=====================================\n");
 91 }
 92 void DownLoad(){
 93     bzero(&recvbuf,sizeof(recvbuf));
 94     bzero(&sentbuf,sizeof(sentbuf));
 95     bzero(filename,sizeof(filename));
 96     printf("Please input the file name:\n");
 97     scanf("%s",sentbuf.buf);
 98     sentbuf.command = DOWNLOAD;
 99     sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server));
100     bcopy(sentbuf.buf,filename,strlen(sentbuf.buf));
101     recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&server,&addrlen);
102     if(recvbuf.command == YES){
103         printf("YES!\n");
104         printf("Start  to transmission!\n");
105             sentbuf.command = START;
106             sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server));
107             int no =0;
108             int fd =open(filename,O_CREAT | O_TRUNC |O_WRONLY,0644);
109             if(fd < 0){
110                 perror("create file error\n");
111                 exit(1);
112             }
113             bzero(&recvbuf,sizeof(recvbuf));
114             while((num = recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&server,&addrlen)) >0){
115                 if(recvbuf.command == CONTENT){
116                     if(no == recvbuf.no){
117                     write(fd,recvbuf.buf,recvbuf.len);
118                     //printf("kkk%s\n",recvbuf.buf );
119                     no++;
120                     bzero(&recvbuf,sizeof(recvbuf));
121                 }
122                 else{
123                     perror("The file no is not same.Some message is missed! error occured! \n");
124                     break;
125                 }
126                 }
127                 if(recvbuf.command == END){
128                     close(fd);
129                     printf("transmission is successful!\n");
130                     break;
131                 }
132             }
133     }
134     else if(recvbuf.command ==NO){
135         perror("NO such file on server!\n");
136     }
137     else{
138         perror("recvbuf.command error\n");
139         exit(1);
140     }
141 }
142 void UpLoad(){
143     bzero(&recvbuf,sizeof(recvbuf));
144     bzero(&sentbuf,sizeof(sentbuf));
145     bzero(filename,sizeof(filename));
146     printf("Please input the file name:\n");
147     scanf("%s",sentbuf.buf);
148     sentbuf.command = UPLOAD;
149     sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server));
150     bcopy(sentbuf.buf,filename,strlen(sentbuf.buf));
151     //判断要传输的文件是否存在
152     int fd;
153     fd = open(filename,O_RDONLY);
154     if(fd < 0){
155         perror("The file you want to trans is not exist!\n");
156         exit(1);
157     }
158     recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&server,&addrlen);
159     if(recvbuf.command == START){
160             int no =0;
161             while((num = read(fd,sentbuf.buf,INFOLEN)) >0){
162                 sentbuf.no = no;
163                 sentbuf.command = CONTENT;
164                 sentbuf.len = strlen(sentbuf.buf);
165                 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server));
166                 no++;
167                 bzero(&sentbuf,sizeof(sentbuf));
168             }
169             bzero(&sentbuf,sizeof(sentbuf));
170             sentbuf.command = END;
171             sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server));
172     }
173     else if(recvbuf.command == NO){
174         printf("not transmission\n");
175         printf("The file is exist!\n");
176     }
177     else {
178         perror("error! wrong choice!\n");
179     }
180 }
181 
182 void ShutDown(){
183     printf("client is shutdown now!\n");
184     bzero(&sentbuf,sizeof(sentbuf));
185     sentbuf.command == SHUTDOWN;
186     sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server));
187 }

3.服务器端程序:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <sys/socket.h>
  5 #include <netinet/in.h>
  6 #include <sys/types.h>
  7 #include <fcntl.h>
  8 #include <sys/stat.h>
  9 #include "protocol.h"
 10 
 11 /*-----------------------变量声明区------------------*/
 12     int socketfd;
 13     int addrlen;
 14     struct sockaddr_in server;
 15     struct sockaddr_in client;
 16     struct protocol sentbuf;
 17     struct protocol recvbuf;
 18     int num;
 19     char ip[20];
 20     int port;
 21     int choice;
 22 
 23 int main(){
 24 
 25     /*-------------create UDP socket------------*/
 26     if((socketfd = socket(AF_INET,SOCK_DGRAM,0)) == -1){
 27         perror("socket error\n");
 28         exit(1);
 29     }
 30 
 31     /*-----------------IO-----------------------*/
 32     printf("Please input the ip:\n");
 33     scanf("%s",ip);
 34     printf("Please input the port:\n");
 35     scanf("%d",&port);
 36 
 37     /*-----------------bind----------------------*/
 38     bzero(&server,sizeof(server));
 39     server.sin_family = AF_INET;
 40     server.sin_port = htons(port);
 41     server.sin_addr.s_addr = inet_addr(ip);
 42     if (bind(socketfd,(struct sockaddr *)&server,sizeof(server)) == -1){
 43         perror("bind error\n");
 44         exit(1);
 45     }
 46 
 47     /*---------------------调试信息------------
 48     addrlen = sizeof(client);
 49     recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&client,&addrlen);
 50     num = strlen(recvbuf.buf);
 51     recvbuf.buf[num] = '\0';
 52     printf("command %d\n",recvbuf.command );
 53     printf("len %d\n",recvbuf.len );
 54     printf("no %d\n", recvbuf.no);
 55     printf("buf %s\n",recvbuf.buf ); */
 56 
 57     addrlen = sizeof(client);
 58     while(1){
 59     bzero(&recvbuf,sizeof(recvbuf));
 60     num =recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&client,&addrlen);
 61     choice = recvbuf.command;
 62     if(choice == DOWNLOAD){
 63         char buf[100];
 64         int fd;
 65         fd = open((recvbuf.buf),O_RDONLY);
 66         if(fd <0){
 67             sentbuf.command = NO;
 68             sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&client,sizeof(client));
 69             printf("no such file!\n");
 70             exit(1);
 71         }
 72         else{
 73             sentbuf.command = YES;
 74             sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&client,sizeof(client));
 75             recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&client,&addrlen);
 76             if(recvbuf.command == START){
 77                 int no =0;
 78                 while((num = read(fd,sentbuf.buf,INFOLEN)) >0){
 79                     sentbuf.no = no;
 80                     sentbuf.command = CONTENT;
 81                     sentbuf.len = strlen(sentbuf.buf);
 82                     sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&client,sizeof(client));
 83                     no++;
 84                     bzero(&sentbuf,sizeof(sentbuf));
 85                 }
 86                 bzero(&sentbuf,sizeof(sentbuf));
 87                 sentbuf.command = END;
 88                 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&client,sizeof(client));
 89             }
 90         }
 91     }
 92     else if(choice == UPLOAD){
 93         int fd1= open(recvbuf.buf,O_RDONLY);
 94         if (fd1 < 0){
 95             sentbuf.command = START;
 96         }
 97         else{
 98             sentbuf.command = NO;
 99         }
100         close(fd1);
101         sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&client,sizeof(client));
102         if(sentbuf.command ==START){
103             int no =0;
104             int fd =open(recvbuf.buf,O_CREAT | O_TRUNC |O_WRONLY,0644);
105             if(fd < 0){
106                 perror("create file error\n");
107                 exit(1);
108             }
109             bzero(&recvbuf,sizeof(recvbuf));
110             while((num = recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&server,&addrlen)) >0){
111                 if(recvbuf.command == CONTENT){
112                     if(no == recvbuf.no){
113                     write(fd,recvbuf.buf,recvbuf.len);
114                     //printf("kkk%s\n",recvbuf.buf );
115                     bzero(&recvbuf,sizeof(recvbuf));
116                 }
117                 else{
118                     perror("The file no is not same.Some message is missed! error occured! \n");
119                     break;
120                 }
121                 }
122                 if(recvbuf.command == END){
123                     close(fd);
124                     printf("transmission is successful!\n");
125                     break;
126                 }
127             }
128         }
129         else if(sentbuf.command == NO){
130             printf("Not to trans the file\n");
131             printf("The file is exist!\n");
132         }
133         else{
134             perror("error! wrong choice!\n");
135             exit(1);
136         }
137 
138     }
139     else if (recvbuf.command == SHUTDOWN){
140         printf("Now the server is shutdown!\n");
141         break;
142     }
143 }
144     
145     /*----------------------close ----------*/
146     close(socketfd);
147     return 0;
148 }

4.makefile文件;

1 main:udpserver.o udpclient.o
2     gcc -o udpserver udpserver.o 
3     gcc -o udpclient udpclient.o 
4 udpserver.o:udpserver.c protocol.h 
5     gcc -c udpserver.c  
6 udpclient.o: udpclient.c protocol.h 
7     gcc -c udpclient.c 
8 clean:
9     rm -rf *.o

代码写的挺烂的,里面有很多重复的代码和功能,完全可以抽取出来做成一个函数的。以后慢慢再改吧。先完成功能,把上机考试过了再说。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一英里广度一英寸深度的学习

Zookeeper 分布式环境中的注册表

ZooKeeper 典型的应用场景,限于篇幅就不详细展开,百度或https://www.jianshu.com/p/1e052bddba80

1343
来自专栏Java编程技术

Spring&Mybaits数据库配置解惑

一般我们会在datasource.xml中进行如下配置,但是其中每个配置项原理和用途是什么,并不是那么清楚,如果不清楚的话,在使用时候就很有可能会遇到坑,所以下...

1232
来自专栏Seebug漏洞平台

Exim Off-by-one(CVE-2018-6789)漏洞复现分析

前段时间meh又挖了一个Exim的RCE漏洞[1],而且这次RCE的漏洞的约束更少了,就算开启了PIE仍然能被利用。虽然去年我研究过Exim,但是时间过去这么久...

1152
来自专栏YG小书屋

ElasticSearch 5.6源码解析HTTP/TCP请求

5013
来自专栏祝威廉

Kafka Zero-Copy 使用分析

Kafka 我个人感觉是性能优化的典范。而且使用Scala开发,代码写的也很漂亮的。重点我觉得有四个

1902
来自专栏恰童鞋骚年

自己动手写工具:百度图片批量下载器

开篇:在某些场景下,我们想要对百度图片搜出来的东东进行保存,但是一个一个得下载保存不仅耗时而且费劲,有木有一种方法能够简化我们的工作量呢,让我们在离线模式下也能...

4191
来自专栏Objective-C

Swift-MVVM 简单演练(二)

3814
来自专栏容器云生态

Docker-client for python使用指南

Docker-client for python使用指南: 客户端初始化的三种方法 import docker docker.api() docker.APIC...

1.1K10
来自专栏杨建荣的学习笔记

Oracle升级中的参数补充(r9笔记第2天)

数据库升级的时候有一个很重要的环节就是数据库参数审核,对于数据库参数还是有很多的门道,其中一种就是对于过期参数的处理。 我们可以使用如下的SQL来得到一个基本...

3099
来自专栏Android研究院

彻底理解OkHttp - OkHttp 源码解析及OkHttp的设计思想

在OKhttp 源码解析之前,我们必须先要了解http的相关基础知识,任何的网络请求都离不开http。

5482

扫码关注云+社区

领取腾讯云代金券