【摘要】 介紹文件發(fā)送、文件接收、線處理服務(wù)器接收、獲取天氣預(yù)報等知識點。
任務(wù)1:網(wǎng)絡(luò)編程
1.1 練習(xí)題說明
1.?實現(xiàn)TCP服務(wù)器與TCP客戶端之間的基本通信,收發(fā)數(shù)據(jù) (按照上課的思路流程看函數(shù)文檔)
2.?實現(xiàn)TCP服務(wù)器與TCP客戶端之間的文件傳輸。(單個文件傳輸)
驗證方式: (1) 同一臺電腦演示 (2)同桌之間演示
考慮的問題:
(1)?網(wǎng)絡(luò)的傳輸環(huán)境,考慮應(yīng)答問題
(2)?數(shù)據(jù)丟包之后如何處理? 可以重發(fā)
(3)?超時處理
(4)?服務(wù)器與客戶端之間連接斷開處理。(客戶端和服務(wù)器兩邊都需要重新連接)
文件傳輸可以在廣告機中使用。
(5)?每個數(shù)據(jù)的單位: 分包發(fā)送
(擴展要求): 顯示接收進(jìn)度百分比,顯示接收的文件名稱,推薦: 定義結(jié)構(gòu)體(使用數(shù)據(jù)結(jié)構(gòu))
3.?(擴展)實現(xiàn)TCP服務(wù)器與TCP客戶端之間的目錄傳輸(一級目錄)。
4.?(擴展)實現(xiàn)網(wǎng)絡(luò)聊天室(模仿QQ群發(fā)送消息的效果)
(1)?加入進(jìn)去的成員都是客戶端
(2)?服務(wù)器負(fù)責(zé)給各個客戶端轉(zhuǎn)發(fā)消
??一般情況下,推薦最大每次傳輸?shù)淖止?jié)數(shù)不超過1024字節(jié)。
(1)文件發(fā)送客戶端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
TCP客戶端:
1. sockt創(chuàng)建套接字
2. 連接服務(wù)器
*/
int socket_cfd; /*保存客戶端套接字*/
int main(int argc,char **argv)
{
if(argc!=4)
{
printf("./server <192.168.xx.xx 服務(wù)器的IP地址> <服務(wù)器端口號> <文件名稱>\n");
exit(-1);
}
FILE *file=fopen(argv[3],"wb");
if(file==NULL)
{
printf("文件創(chuàng)建失敗!");
exit(0);
}
int err; //存放返回值狀態(tài)
/*1. 創(chuàng)建套接字*/
socket_cfd=socket(AF_INET,SOCK_STREAM,0);
if(socket_cfd<0)
{
printf("服務(wù)器端創(chuàng)建失敗!\n");
exit(-1);
}
/*2.連接服務(wù)器*/
struct sockaddr_in ServerAddr;
ServerAddr.sin_family=AF_INET; //IPV4協(xié)議
ServerAddr.sin_port=htons(atoi(argv[2])); //服務(wù)器的端口號 最大值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("服務(wù)器連接失敗!\n");
exit(-1);
}
/*3. 收發(fā)數(shù)據(jù): 接收服務(wù)器發(fā)送的數(shù)據(jù)*/
char rx_buff[100];
fd_set readfds; //存放讀事件
int data;
int ack=666;
while(1)
{
FD_ZERO(&readfds); //清空文件描述符
FD_SET(socket_cfd,&readfds); //添加需要監(jiān)控的文件描述符
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("服務(wù)器已經(jīng)與客戶端斷開連接!\n");
break;
}
fwrite(rx_buff,1,err,file);//寫入數(shù)據(jù)
printf("客戶端成功接收%d個字節(jié)\n",err);
write(socket_cfd,&ack,4); //發(fā)送應(yīng)答信號。
}
}
close(socket_cfd);
fclose(file);
return 0;
}
(2)文件發(fā)送客戶端
#include
#include
#include
#include
#include
#include
/*
TCP服務(wù)器:
1. sockt創(chuàng)建套接字
2. bind綁定端口
3. 設(shè)置監(jiān)聽的數(shù)量
4. 等待客戶端連接
*/
int socket_sfd; /*保存了服務(wù)器端的套接字*/
int socket_cfd; /*已經(jīng)連接成功的客戶端套接字*/
/*
服務(wù)器是發(fā)送端
*/
int main(int argc,char **argv)
{
if(argc!=4)
{
printf("./server <192.168.xx.xx 本地IP地址> <服務(wù)器端口號> \n");
exit(-1);
}
FILE *file=fopen(argv[3],"rb");
if(file==NULL)
{
printf("文件打開失敗!\n");
exit(0);
}
int err; //存放返回值狀態(tài)
/*1. 創(chuàng)建套接字*/
socket_sfd=socket(AF_INET,SOCK_STREAM,0);
if(socket_sfd<0)
{
printf("服務(wù)器端創(chuàng)建失敗!\n");
exit(-1);
}
/*2. 綁定端口*/
struct sockaddr_in ServerAddr;
ServerAddr.sin_family=AF_INET; //IPV4協(xié)議
ServerAddr.sin_port=htons(atoi(argv[2])); //服務(wù)器的端口號 最大值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("服務(wù)器端 端口綁定失敗!\n");
exit(-1);
}
/*3. 設(shè)置監(jiān)聽的數(shù)量*/
listen(socket_sfd,10);
/*4. 等待客戶端連接*/
struct sockaddr_in ClientAddr; //存放已經(jīng)連接成功客戶端信息
socklen_t addrlen=sizeof(struct sockaddr); //客戶端的地址長度
socket_cfd=accept(socket_sfd,(struct sockaddr *)&ClientAddr,&addrlen);
if(socket_cfd<0)
{
printf("服務(wù)器端,連接客戶端失敗!\r\n");
exit(-1);
}
/*打印一些客戶端的信息*/
printf("成功連接的客戶端端口號:%d\n",ntohs(ClientAddr.sin_port));
printf("成功連接的客戶端IP地址:%s\n",inet_ntoa(ClientAddr.sin_addr));
/*5. 收發(fā)數(shù)據(jù) :服務(wù)器給客戶端發(fā)送10個字節(jié)的數(shù)據(jù)*/
char tx_buff[100];
int len;
int ack;
while(1)
{
len=fread(tx_buff,1,100,file);
printf("服務(wù)器成功發(fā)送:%d 字節(jié)\r\n",len);
err=write(socket_cfd,tx_buff,len);
while(1)
{
err=read(socket_cfd,&ack,4); //等待客戶端的應(yīng)答
if(err>0&&ack==666)
{
break;
}
}
if(len!=100)break;
}
close(socket_sfd);
fclose(file);
return 0;
}
文件名稱>
任務(wù)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 |
練習(xí):
1.?學(xué)習(xí)線程的基本使用
2.?實現(xiàn)一個服務(wù)器實現(xiàn)多個客戶端的連接,實現(xiàn)通信。
思路: 一個客戶端就是一個獨立的線程。
3.?擴展練習(xí): 實現(xiàn)服務(wù)器同時對多個客戶端進(jìn)行文件發(fā)送。
(1)?服務(wù)器連接上一個客戶端就創(chuàng)建一個線程。
(2)?線程的函數(shù)需要寫幾個? 1個
1個函數(shù)需要考慮的問題: 函數(shù)的可重入性能!
需要考慮到資源搶占! 使用信號量!
1.?CRC16、CRC32校驗、
2.?和校驗 ”abcd <校驗和>” -->和
3.?異或校驗。 (1) 文件加密解碼
(2) 不添加三個變量,將兩個變量的值交換
int a=666; int b=888;
4.?MD5值校驗。
客戶端:
#include
#include /* See NOTES */
#include
#include //使用大小端轉(zhuǎn)換函數(shù). find /
#include
/*服務(wù)器端口號定義*/
#define P_host 8080
// ./app 192.168.18.3
/*TCP客戶端代碼*/
int main(int argc,char *argv[])
{
if(argc!=2)
{
printf("參數(shù)錯誤:./app <服務(wù)器IP地址>\n");
return -1;
}
int clientfd;
struct sockaddr_in server_address; //存放服務(wù)器的IP地址信息
memset(&server_address,0,sizeof(struct sockaddr_in)); //初始化內(nèi)存空間
server_address.sin_family=AF_INET; //IPV4協(xié)議
server_address.sin_port=htons(P_host); //端口號賦值
server_address.sin_addr.s_addr=inet_addr(argv[1]); //本地IP地址
/*1 .創(chuàng)建套接字*/
clientfd=socket(AF_INET,SOCK_STREAM,0);
if(clientfd<0)
{
printf("客戶端網(wǎng)絡(luò)套接字創(chuàng)建失敗!\n");
return -1;
}
/*2. 連接服務(wù)器*/
if(connect(clientfd,(const struct sockaddr *)&server_address,sizeof(struct sockaddr))!=0)
{
printf("客戶端連接服務(wù)器失敗!\n");
return -1;
}
char buff[1024];
while(1)
{
gets(buff);
write(clientfd,buff,strlen(buff));
}
return 0;
}
服務(wù)器:
#include
#include /* See NOTES */
#include
#include //使用大小端轉(zhuǎn)換函數(shù)
#include
#include
#include
#include
#include
#include
//函數(shù)聲明
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]; //存放線程的標(biāo)識符
int clientfd[2]; //保存TCP客戶端的網(wǎng)絡(luò)套接字
struct sockaddr_in client_address[2]; //存放客戶端的信息
socklen_t address_len[2]; //存放客戶端結(jié)構(gòu)體信息的長度
/*服務(wù)器端口號定義*/
#define P_host 8080
/*TCP服務(wù)器代碼*/
int main(int argc,char *argv[])
{
int socketfd;
struct sockaddr_in server_address; //存放服務(wù)器的IP地址信息
memset(&server_address,0,sizeof(struct sockaddr_in)); //初始化內(nèi)存空間
memset(client_address,0,sizeof(struct sockaddr_in)*2); //初始化內(nèi)存空間
server_address.sin_family=PF_INET; //IPV4協(xié)議
server_address.sin_port=htons(P_host); //端口號賦值
server_address.sin_addr.s_addr=INADDR_ANY; //本地IP地址
/*1 .創(chuàng)建套接字*/
socketfd=socket(PF_INET,SOCK_STREAM,0);
if(socketfd<0)
{
printf("服務(wù)器網(wǎng)絡(luò)套接字創(chuàng)建失敗!\n");
return -1;
}
/*2. 綁定端口,創(chuàng)建服務(wù)器*/
if(bind(socketfd,(const struct sockaddr *)&server_address,sizeof(struct sockaddr))!=0)
{
printf("服務(wù)器綁定端口失敗!\n");
return -1;
}
/*3. 設(shè)監(jiān)聽的端口數(shù)量*/
if(listen(socketfd,10)!=0)
{
printf("服務(wù)器端口監(jiān)聽失敗!\n");
return -1;
}
int i;
for(i=0;i<2;i++)
{
address_len[i]=sizeof(struct sockaddr); //計算結(jié)構(gòu)體大小 20
/*4. 等待客戶端連接*/
if((clientfd[i]=accept(socketfd,(struct sockaddr *)&client_address[i],&address_len[i]))<0)
{
printf("等待客戶端連接失敗!\n");
break;
}
//創(chuàng)建線程
if(pthread_create(&thread_id[i],NULL,fun[i],NULL)!=0)
{
printf("線程_%d_創(chuàng)建失敗!\n",i);
}
}
while(1)
{
}
//阻塞方式等待線程的結(jié)束
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);
}
任務(wù)3:使用的網(wǎng)絡(luò)服務(wù)器接口
C語言:面向過程 、 面向?qū)ο?/p>
1.?車牌號識別
2.?二維碼生成
3.?獲取北京時間
獲取接口的網(wǎng)址:http://www.k780.com/
1.?調(diào)用網(wǎng)絡(luò)的接口的方式: (天氣預(yù)報)
curl http://api.k780.com:88/?app=weather.future'&'weaid=南昌 '&&'appkey=10003'&'sign=b59bc3ef6191eb9f747dd4e83c99f2a4'&'format=json >123.txt |
注意: &是特殊的符號,需要使用單引號或者雙引號括起來。
Curl: 命令行的瀏覽器。
2.?調(diào)用二維碼生成的接口
curl http://api.k780.com:88/?app=qr.get'&'data=www.wanbangee.com'&'level=L'&'size=6 >123.png |
?? 練習(xí):
1.?天氣預(yù)報查詢
查詢的格式: ./app <城市的中文名稱>
2.?獲取北京標(biāo)準(zhǔn)時間,顯示出來
3.?二維碼生成創(chuàng)建 運行格式: ./app <生成的二維碼內(nèi)容>
生成之后直接顯示在屏幕上??梢允褂胑og命令
4.?車牌號的識別
5.?調(diào)用百度地圖API接口 http://lbsyun.baidu.com/index.php?title=uri/api/web
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
9123瀏覽量
85322 -
TCP
+關(guān)注
關(guān)注
8文章
1353瀏覽量
79055 -
文件
+關(guān)注
關(guān)注
1文章
565瀏覽量
24727
發(fā)布評論請先 登錄
相關(guān)推薦
評論