首页 > 技术知识 > 正文

【摘要】 介绍文件发送、文件接收、线处理服务器接收、获取天气预报等知识点。

任务1:网络编程

1.1 练习题说明

1.​实现TCP服务器与TCP客户端之间的基本通信,收发数据 (按照上课的思路流程看函数文档)

2.​实现TCP服务器与TCP客户端之间的文件传输。(单个文件传输)

验证方式: (1) 同一台电脑演示 (2)同桌之间演示

考虑的问题:

(1)​网络的传输环境,考虑应答问题

(2)​数据丢包之后如何处理? 可以重发

(3)​超时处理

(4)​服务器与客户端之间连接断开处理。(客户端和服务器两边都需要重新连接)

文件传输可以在广告机中使用。

(5)​每个数据的单位: 分包发送

(扩展要求): 显示接收进度百分比,显示接收的文件名称,推荐: 定义结构体(使用数据结构)

3.​(扩展)实现TCP服务器与TCP客户端之间的目录传输(一级目录)。

4.​(扩展)实现网络聊天室(模仿QQ群发送消息的效果)

(1)​加入进去的成员都是客户端

(2)​服务器负责给各个客户端转发消

​一般情况下,推荐最大每次传输的字节数不超过1024字节。

(1)文件发送客户端

复制#include #include #include #include #include #include #include #include #include #include /* TCP客户端: 1. sockt创建套接字 2. 连接服务器 */ int socket_cfd; /*保存客户端套接字*/ int main(int argc,char **argv) { if(argc!=4) { printf(“./server <192.168.xx.xx 服务器的IP地址> <服务器端口号> <文件名称>\n”); exit(-1); } FILE *file=fopen(argv[3],”wb”); if(file==NULL) { printf(“文件创建失败!”); exit(0); } int err; //存放返回值状态 /*1. 创建套接字*/ socket_cfd=socket(AF_INET,SOCK_STREAM,0); if(socket_cfd<0) { printf(“服务器端创建失败!\n”); exit(-1); } /*2.连接服务器*/ struct sockaddr_in ServerAddr; ServerAddr.sin_family=AF_INET; //IPV4协议 ServerAddr.sin_port=htons(atoi(argv[2])); //服务器的端口号 最大值65535 ServerAddr.sin_addr.s_addr=inet_addr(argv[1]); //IP地址赋值 err=connect(socket_cfd,(const struct sockaddr *)&ServerAddr,sizeof(struct sockaddr)); if(err!=0) { printf(“服务器连接失败!\n”); exit(-1); } /*3. 收发数据: 接收服务器发送的数据*/ char rx_buff[100]; fd_set readfds; //存放读事件 int data; int ack=666; while(1) { FD_ZERO(&readfds); //清空文件描述符 FD_SET(socket_cfd,&readfds); //添加需要监控的文件描述符 data=select(socket_cfd+1,&readfds,NULL,NULL,NULL); if(data>0) { err=read(socket_cfd,rx_buff,100); if(err==0 && data==1) { printf(“服务器已经与客户端断开连接!\n”); break; } fwrite(rx_buff,1,err,file);//写入数据 printf(“客户端成功接收%d个字节\n”,err); write(socket_cfd,&ack,4); //发送应答信号。 } } close(socket_cfd); fclose(file); return 0; }

(2)文件发送客户端

复制#include #include #include #include #include #include /* TCP服务器: 1. sockt创建套接字 2. bind绑定端口 3. 设置监听的数量 4. 等待客户端连接 */ int socket_sfd; /*保存了服务器端的套接字*/ int socket_cfd; /*已经连接成功的客户端套接字*/ /* 服务器是发送端 */ int main(int argc,char **argv) { if(argc!=4) { printf(“./server <192.168.xx.xx 本地IP地址> <服务器端口号> \n”); exit(-1); } FILE *file=fopen(argv[3],”rb”); if(file==NULL) { printf(“文件打开失败!\n”); exit(0); } int err; //存放返回值状态 /*1. 创建套接字*/ socket_sfd=socket(AF_INET,SOCK_STREAM,0); if(socket_sfd<0) { printf(“服务器端创建失败!\n”); exit(-1); } /*2. 绑定端口*/ struct sockaddr_in ServerAddr; ServerAddr.sin_family=AF_INET; //IPV4协议 ServerAddr.sin_port=htons(atoi(argv[2])); //服务器的端口号 最大值65535 ServerAddr.sin_addr.s_addr=inet_addr(argv[1]); //IP地址赋值 err=bind(socket_sfd,(const struct sockaddr *)&ServerAddr,sizeof(struct sockaddr)); if(err!=0) { printf(“服务器端 端口绑定失败!\n”); exit(-1); } /*3. 设置监听的数量*/ listen(socket_sfd,10); /*4. 等待客户端连接*/ struct sockaddr_in ClientAddr; //存放已经连接成功客户端信息 socklen_t addrlen=sizeof(struct sockaddr); //客户端的地址长度 socket_cfd=accept(socket_sfd,(struct sockaddr *)&ClientAddr,&addrlen); if(socket_cfd<0) { printf(“服务器端,连接客户端失败!\r\n”); exit(-1); } /*打印一些客户端的信息*/ printf(“成功连接的客户端端口号:%d\n”,ntohs(ClientAddr.sin_port)); printf(“成功连接的客户端IP地址:%s\n”,inet_ntoa(ClientAddr.sin_addr)); /*5. 收发数据 :服务器给客户端发送10个字节的数据*/ char tx_buff[100]; int len; int ack; while(1) { len=fread(tx_buff,1,100,file); printf(“服务器成功发送:%d 字节\r\n”,len); err=write(socket_cfd,tx_buff,len); while(1) { err=read(socket_cfd,&ack,4); //等待客户端的应答 if(err>0&&ack==666) { break; } } if(len!=100)break; } close(socket_sfd); fclose(file); return 0; } 文件名称>

任务2:线程编程

#include

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

void *(*start_routine) (void *), void *arg);

Compile and link with -pthread.

-lpthread

理解: 一个线程就是一个while(1)。

[root@wbyq linux-share-dir]# gcc app.c

/tmp/cccOs4TK.o: In function `main:

app.c:(.text+0x69): undefined reference to `pthread_create

app.c:(.text+0x8d): undefined reference to `pthread_create

collect2: ld 返回 1

[root@wbyq linux-share-dir]# gcc app.c -lpthread

练习:

1.​学习线程的基本使用

2.​实现一个服务器实现多个客户端的连接,实现通信。

思路: 一个客户端就是一个独立的线程。

3.​扩展练习: 实现服务器同时对多个客户端进行文件发送。

(1)​服务器连接上一个客户端就创建一个线程。

(2)​线程的函数需要写几个? 1个

1个函数需要考虑的问题: 函数的可重入性能!

需要考虑到资源抢占! 使用信号量!

1.​CRC16、CRC32校验、

2.​和校验 ”abcd <校验和>” –>和

3.​异或校验。 (1) 文件加密解码

(2) 不添加三个变量,将两个变量的值交换

int a=666; int b=888;

4.​MD5值校验。

客户端:

复制#include #include /* See NOTES */ #include #include //使用大小端转换函数. find / #include /*服务器端口号定义*/ #define P_host 8080 // ./app 192.168.18.3 /*TCP客户端代码*/ int main(int argc,char *argv[]) { if(argc!=2) { printf(“参数错误:./app <服务器IP地址>\n”); return -1; } int clientfd; struct sockaddr_in server_address; //存放服务器的IP地址信息 memset(&server_address,0,sizeof(struct sockaddr_in)); //初始化内存空间 server_address.sin_family=AF_INET; //IPV4协议 server_address.sin_port=htons(P_host); //端口号赋值 server_address.sin_addr.s_addr=inet_addr(argv[1]); //本地IP地址 /*1 .创建套接字*/ clientfd=socket(AF_INET,SOCK_STREAM,0); if(clientfd<0) { printf(“客户端网络套接字创建失败!\n”); return -1; } /*2. 连接服务器*/ if(connect(clientfd,(const struct sockaddr *)&server_address,sizeof(struct sockaddr))!=0) { printf(“客户端连接服务器失败!\n”); return -1; } char buff[1024]; while(1) { gets(buff); write(clientfd,buff,strlen(buff)); } return 0; }

服务器:

复制#include #include /* See NOTES */ #include #include //使用大小端转换函数 #include #include #include #include #include #include //函数声明 void *start_routine_1(void *dev); void *start_routine_2(void *dev); typedef void *(*start_routine) (void *); start_routine fun[]={start_routine_1,start_routine_2}; pthread_t thread_id[2]; //存放线程的标识符 int clientfd[2]; //保存TCP客户端的网络套接字 struct sockaddr_in client_address[2]; //存放客户端的信息 socklen_t address_len[2]; //存放客户端结构体信息的长度 /*服务器端口号定义*/ #define P_host 8080 /*TCP服务器代码*/ int main(int argc,char *argv[]) { int socketfd; struct sockaddr_in server_address; //存放服务器的IP地址信息 memset(&server_address,0,sizeof(struct sockaddr_in)); //初始化内存空间 memset(client_address,0,sizeof(struct sockaddr_in)*2); //初始化内存空间 server_address.sin_family=PF_INET; //IPV4协议 server_address.sin_port=htons(P_host); //端口号赋值 server_address.sin_addr.s_addr=INADDR_ANY; //本地IP地址 /*1 .创建套接字*/ socketfd=socket(PF_INET,SOCK_STREAM,0); if(socketfd<0) { printf(“服务器网络套接字创建失败!\n”); return -1; } /*2. 绑定端口,创建服务器*/ if(bind(socketfd,(const struct sockaddr *)&server_address,sizeof(struct sockaddr))!=0) { printf(“服务器绑定端口失败!\n”); return -1; } /*3. 设监听的端口数量*/ if(listen(socketfd,10)!=0) { printf(“服务器端口监听失败!\n”); return -1; } int i; for(i=0;i<2;i++) { address_len[i]=sizeof(struct sockaddr); //计算结构体大小 20 /*4. 等待客户端连接*/ if((clientfd[i]=accept(socketfd,(struct sockaddr *)&client_address[i],&address_len[i]))<0) { printf(“等待客户端连接失败!\n”); break; } //创建线程 if(pthread_create(&thread_id[i],NULL,fun[i],NULL)!=0) { printf(“线程_%d_创建失败!\n”,i); } } while(1) { } //阻塞方式等待线程的结束 pthread_join(thread_id[0],NULL); pthread_join(thread_id[1],NULL); return 0; } //线程1 void *start_routine_1(void *dev) { while(1) { printf(“TCP客户端1连接!\n”); sleep(2); } //终止线程 pthread_exit(NULL); } //线程2 void *start_routine_2(void *dev) { while(1) { printf(“TCP客户端2连接!\n”); sleep(2); } //终止线程 pthread_exit(NULL); }

任务3:使用的网络服务器接口

C语言:面向过程 、 面向对象

1.​车牌号识别

2.​二维码生成

3.​获取北京时间

获取接口的网址:http://www.k780.com/

1.​调用网络的接口的方式: (天气预报)

curl http://api.k780.com:88/?app=weather.future&weaid=南昌

&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json >123.txt

注意: &是特殊的符号,需要使用单引号或者双引号括起来。

Curl: 命令行的浏览器。

2.​调用二维码生成的接口

curl http://api.k780.com:88/?app=qr.get&data=www.wanbangee.com&level=L&size=6 >123.png

​ 练习:

1.​天气预报查询

查询的格式: ./app <城市的中文名称>

Linux开发_文件发送与接收-如何给linux传输文件

2.​获取北京标准时间,显示出来

Linux开发_文件发送与接收-如何给linux传输文件1

3.​二维码生成创建 运行格式: ./app <生成的二维码内容>

生成之后直接显示在屏幕上。可以使用eog命令

4.​车牌号的识别

5.​调用百度地图API接口 http://lbsyun.baidu.com/index.php?title=uri/api/web

猜你喜欢