激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - C/C++ - Linux網(wǎng)絡(luò)編程之基于UDP實(shí)現(xiàn)可靠的文件傳輸示例

Linux網(wǎng)絡(luò)編程之基于UDP實(shí)現(xiàn)可靠的文件傳輸示例

2021-01-28 15:03C語(yǔ)言程序設(shè)計(jì) C/C++

這篇文章主要介紹了Linux網(wǎng)絡(luò)編程之基于UDP實(shí)現(xiàn)可靠的文件傳輸示例,是很實(shí)用的技巧,需要的朋友可以參考下

了解網(wǎng)絡(luò)傳輸協(xié)議的人都知道,采用TCP實(shí)現(xiàn)文件傳輸很簡(jiǎn)單。相對(duì)于TCP,由于UDP是面向無(wú)連接、不可靠的傳輸協(xié)議,所以我們需要考慮丟包和后發(fā)先至(包的順序)的問(wèn)題,所以我們想要實(shí)現(xiàn)UDP傳輸文件,則需要解決這兩個(gè)問(wèn)題。方法就是給數(shù)據(jù)包編號(hào),按照包的順序接收并存儲(chǔ),接收端接收到數(shù)據(jù)包后發(fā)送確認(rèn)信息給發(fā)送端,發(fā)送端接收確認(rèn)數(shù)據(jù)以后再繼續(xù)發(fā)送下一個(gè)包,如果接收端收到的數(shù)據(jù)包的編號(hào)不是期望的編號(hào),則要求發(fā)送端重新發(fā)送。

下面展示的是基于linux下C語(yǔ)言實(shí)現(xiàn)的一個(gè)示例程序,該程序定義一個(gè)包的結(jié)構(gòu)體,其中包含數(shù)據(jù)和包頭,包頭里包含有包的編號(hào)和數(shù)據(jù)大小,經(jīng)過(guò)測(cè)試后,該程序可以成功傳輸一個(gè)視頻文件。

具體實(shí)現(xiàn)代碼如下:

server端代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*************************************************************************
  > File Name: server.c
  > Author: SongLee
 ************************************************************************/
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<netdb.h>
#include<stdarg.h>
#include<string.h>
 
#define SERVER_PORT 8000
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512
 
/* 包頭 */
typedef struct
{
  int id;
  int buf_size;
}PackInfo;
 
/* 接收包 */
struct SendPack
{
  PackInfo head;
  char buf[BUFFER_SIZE];
} data;
 
 
int main()
{
  /* 發(fā)送id */
  int send_id = 0;
 
  /* 接收id */
  int receive_id = 0;
 
  /* 創(chuàng)建UDP套接口 */
  struct sockaddr_in server_addr;
  bzero(&server_addr, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  server_addr.sin_port = htons(SERVER_PORT);
 
  /* 創(chuàng)建socket */
  int server_socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
  if(server_socket_fd == -1)
  {
    perror("Create Socket Failed:");
    exit(1);
  }
 
  /* 綁定套接口 */
  if(-1 == (bind(server_socket_fd,(struct sockaddr*)&server_addr,sizeof(server_addr))))
  {
    perror("Server Bind Failed:");
    exit(1);
  }
 
  /* 數(shù)據(jù)傳輸 */
  while(1)
  {  
    /* 定義一個(gè)地址,用于捕獲客戶端地址 */
    struct sockaddr_in client_addr;
    socklen_t client_addr_length = sizeof(client_addr);
 
    /* 接收數(shù)據(jù) */
    char buffer[BUFFER_SIZE];
    bzero(buffer, BUFFER_SIZE);
    if(recvfrom(server_socket_fd, buffer, BUFFER_SIZE,0,(struct sockaddr*)&client_addr, &client_addr_length) == -1)
    {
      perror("Receive Data Failed:");
      exit(1);
    }
 
    /* 從buffer中拷貝出file_name */
    char file_name[FILE_NAME_MAX_SIZE+1];
    bzero(file_name,FILE_NAME_MAX_SIZE+1);
    strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));
    printf("%s\n", file_name);
 
    /* 打開(kāi)文件 */
    FILE *fp = fopen(file_name, "r");
    if(NULL == fp)
    {
      printf("File:%s Not Found.\n", file_name);
    }
    else
    {
      int len = 0;
      /* 每讀取一段數(shù)據(jù),便將其發(fā)給客戶端 */
      while(1)
      {
        PackInfo pack_info;
 
        if(receive_id == send_id)
        {
          ++send_id;
          if((len = fread(data.buf, sizeof(char), BUFFER_SIZE, fp)) > 0)
          {
            data.head.id = send_id; /* 發(fā)送id放進(jìn)包頭,用于標(biāo)記順序 */
            data.head.buf_size = len; /* 記錄數(shù)據(jù)長(zhǎng)度 */
            if(sendto(server_socket_fd, (char*)&data, sizeof(data), 0, (struct sockaddr*)&client_addr, client_addr_length) < 0)
            {
              perror("Send File Failed:");
              break;
            }
            /* 接收確認(rèn)消息 */
            recvfrom(server_socket_fd, (char*)&pack_info, sizeof(pack_info), 0, (struct sockaddr*)&client_addr, &client_addr_length);
            receive_id = pack_info.id; 
          }
          else
          {
            break;
          }
        }
        else
        {
          /* 如果接收的id和發(fā)送的id不相同,重新發(fā)送 */
          if(sendto(server_socket_fd, (char*)&data, sizeof(data), 0, (struct sockaddr*)&client_addr, client_addr_length) < 0)
          {
            perror("Send File Failed:");
            break;
          }
          /* 接收確認(rèn)消息 */
          recvfrom(server_socket_fd, (char*)&pack_info, sizeof(pack_info), 0, (struct sockaddr*)&client_addr, &client_addr_length);
          receive_id = pack_info.id; 
        }
      }
      /* 關(guān)閉文件 */
      fclose(fp);
      printf("File:%s Transfer Successful!\n", file_name);
    }
  }
  close(server_socket_fd);
  return 0;
}

client端代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*************************************************************************
  > File Name: client.c
  > Author: SongLee
 ************************************************************************/
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<netdb.h>
#include<stdarg.h>
#include<string.h>
 
#define SERVER_PORT 8000
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512
 
/* 包頭 */
typedef struct
{
  int id;
  int buf_size;
}PackInfo;
 
/* 接收包 */
struct RecvPack
{
  PackInfo head;
  char buf[BUFFER_SIZE];
} data;
 
 
int main()
{
  int id = 1;
 
  /* 服務(wù)端地址 */
  struct sockaddr_in server_addr;
  bzero(&server_addr, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  server_addr.sin_port = htons(SERVER_PORT);
  socklen_t server_addr_length = sizeof(server_addr);
 
  /* 創(chuàng)建socket */
  int client_socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
  if(client_socket_fd < 0)
  {
    perror("Create Socket Failed:");
    exit(1);
  }
 
  /* 輸入文件名到緩沖區(qū) */
  char file_name[FILE_NAME_MAX_SIZE+1];
  bzero(file_name, FILE_NAME_MAX_SIZE+1);
  printf("Please Input File Name On Server: ");
  scanf("%s", file_name);
 
  char buffer[BUFFER_SIZE];
  bzero(buffer, BUFFER_SIZE);
  strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE?BUFFER_SIZE:strlen(file_name));
 
  /* 發(fā)送文件名 */
  if(sendto(client_socket_fd, buffer, BUFFER_SIZE,0,(struct sockaddr*)&server_addr,server_addr_length) < 0)
  {
    perror("Send File Name Failed:");
    exit(1);
  }
 
  /* 打開(kāi)文件,準(zhǔn)備寫入 */
  FILE *fp = fopen(file_name, "w");
  if(NULL == fp)
  {
    printf("File:\t%s Can Not Open To Write\n", file_name); 
    exit(1);
  }
 
  /* 從服務(wù)器接收數(shù)據(jù),并寫入文件 */
  int len = 0;
  while(1)
  {
    PackInfo pack_info;
 
    if((len = recvfrom(client_socket_fd, (char*)&data, sizeof(data), 0, (struct sockaddr*)&server_addr,&server_addr_length)) > 0)
    {
      if(data.head.id == id)
      {
        pack_info.id = data.head.id;
        pack_info.buf_size = data.head.buf_size;
        ++id;
        /* 發(fā)送數(shù)據(jù)包確認(rèn)信息 */
        if(sendto(client_socket_fd, (char*)&pack_info, sizeof(pack_info), 0, (struct sockaddr*)&server_addr, server_addr_length) < 0)
        {
          printf("Send confirm information failed!");
        }
        /* 寫入文件 */
        if(fwrite(data.buf, sizeof(char), data.head.buf_size, fp) < data.head.buf_size)
        {
          printf("File:\t%s Write Failed\n", file_name);
          break;
        }
      }
      else if(data.head.id < id) /* 如果是重發(fā)的包 */
      {
        pack_info.id = data.head.id;
        pack_info.buf_size = data.head.buf_size;
        /* 重發(fā)數(shù)據(jù)包確認(rèn)信息 */
        if(sendto(client_socket_fd, (char*)&pack_info, sizeof(pack_info), 0, (struct sockaddr*)&server_addr, server_addr_length) < 0)
        {
          printf("Send confirm information failed!");
        }
      }
      else
      {
 
      }
    }
    else
    {
      break;
    }
  }
 
  printf("Receive File:\t%s From Server IP Successful!\n", file_name);
  fclose(fp);
  close(client_socket_fd);
  return 0;
}

感興趣的朋友可以動(dòng)手測(cè)試一下該程序,相信會(huì)對(duì)大家的Linux下C語(yǔ)言網(wǎng)絡(luò)編程帶來(lái)一定的幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美a视频在线观看 | 人人舔人人舔 | 国产精品成人亚洲一区二区 | 欧美日韩网站在线观看 | 国产成人在线观看网站 | 欧美高清第一页 | 国产在线精品一区二区三区 | 深夜影院一级毛片 | 亚洲第一页视频 | 亚洲欧美日韩免费 | 成人在线视频免费观看 | 蜜桃麻豆视频 | 偷偷草网站 | 一级做a爱片久久毛片a高清 | 毛片一区二区三区四区 | 毛片一区二区三区 | 久久久国产精品视频 | 久久精品中文字幕一区二区三区 | 国产欧美在线观看不卡一 | 91久久国产综合久久91猫猫 | 中国产一级毛片 | 欧美福利视频一区二区 | h视频免费在线观看 | av噜噜在线| 久久狂草 | av在线免费观看国产 | 欧美999 | 久久艹逼 | 亚洲人成电影在线 | 91久久久久久久一区二区 | 青草av.久久免费一区 | 成人福利在线 | 一级全毛片 | 91超在线 | 12av毛片 | 久久精品亚洲欧美日韩精品中文字幕 | 久久不射电影 | 午夜影院在线免费观看 | 国产在线播放一区二区 | 一级成人黄色片 | 成人h精品动漫一区二区三区 |