技術共有

ネットワークプログラミング: 基本概念

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1. OSIモデル

OSI モデル ===》オープン システム相互接続モデル ==》は 7 つの層に分かれています。
理想モデル ==》まだ実現されていない
FTPサーバ
b /etc/passwd
/etc/123 に
アプリケーション層
プレゼンテーション層の暗号化と復号化 gzip
セッション層ネットワークの切断、接続ステータス、キープクローズキープアライブ

トランスポート層 tcp udp プロトコル ファイル ビデオ、オーディオ
ネットワーク層IP NAT

リンク層スイッチのデータフォーマットフレームチェック
物理層 100Mb/8 Gbits 100MB 同軸ケーブル 10Gb 2.4G 5G

下から上へ、下が最も基本的なものです

2. TCP/IPモデル

TCP/IP モデル ==》インターネット モデル ==》は 4 つの層に分かれています。
実用新案 ===》業界標準
tcp/ipプロトコルスタック
アプリケーション層 ====》アプリケーション
トランスポート層 ====》ポート番号 tcp udp (どの伝送方式が使用されているか、信頼できるTCPUDPはリアルタイム性能が高い
ネットワーク層 ====》IPアドレス(相手とホストの探し方
インターフェース層 ====》ネットワークカードドライバー 1GB
pcap ,,,

3. TCP/IPプロトコルスイート

www.taobao.com ---> 192.168.0.19
www.voa.com VPN
DNS ドメイン名解決 (通常は州に基づく)


DHCP (動的ホスト構成プロトコル)
アプリケーション層:HTTP (ウェブページ) TFTP (単純な短距離ファイル転送)FTP(インターネット長距離転送)
                   SNMP (ネットワークデバイス、システム、アプリケーションの管理と監視)DNS ...
トランスポート層: TCP UDP 56k cat
ネットワーク層: IP ICMP (ping) RIP OSPF IGMP...
インターフェイス層: ARP (アドレス解決プロトコル) RARP... ip--->mac
アルプ、、、、
    192.160.0.112 


1. ネットワークの基本

ネットワークの基礎 ===》ABCDEクラス
010  3333344444
IP アドレス == ネットワーク ビット + ホスト ビット

IP アドレス分類: ドット 10 進数 ipv4 712934
    カテゴリーA:非常に大規模なネットワーク
                          8    8     8    8
        1.0.0.0 - 126.255.255.255  126.1.1.1 
        ネットワークID                                126.1.1.2
       255.0.0.0 (サブネットマスク)  
プライベート:
        10.0.0.0 - 10.255.255.255
        127.0.0.1
    カテゴリーB: 大規模および中規模のネットワーク
        128.0.0.0 - 191.255.255.255
        128.2.1.2  128.2.7.2
        255.255.0.0
プライベート:
        172.16.0.0 - 172.31.255.255

   カテゴリーC: 中小規模のネットワーク
       192.0.0.0 - 223.255.255.255
        255.255.255.0
プライベート:
       192.168.0.0 - 192.168.255.255
静的ルーティング
        192.168.0.0
        192.168.0.1 ゲートウェイ
        192.168.0.255 (ブロードキャスト、LAN 上の全員が受信可能)

   カテゴリD: マルチキャストと放送
        224.0.0.0 ~ 239.255.255.255 (グループチャット、誰でも参加できるわけではない、LAN に限定されない)
        192.168.0.255 == 255.255.255.255 (LANのみ、1人が送信、全員が受信)
        235.1.2.3
        192.168.1.0 
192.168.0.1 ゲートウェイ
192.168.1.255 ブロードキャスト

カテゴリ E: 実験的
        240.0.0.0 - 255.255.255.255
        
クラスCネットワーク:
IP アドレスの最初の 3 つのグループはネットワーク アドレスで、4 番目のグループはホスト アドレスです。
バイナリの最上位ビットは次のようにする必要があります: 110xxxxx で始まる
10 進数表現の範囲: 192.0.0.0 -223.255.255.255
デフォルトのネットマスク: 255.255.255.0
ネットワーク数:2^24、約209万
ホスト数: 2^8 254 + 2 ===》1 はゲートウェイ 1 はブロードキャスト
プライベートアドレス: 192.168.xx LAN アドレス。
  
  sudo vim/etc/network/interfaces "ネットワークの構成"
sudo /etc/init.d/networkingを再起動します
sudo 再起動
    192.168.0.0
192.168.0.1 ルート
192.168.0.255 ボードキャスト
801.ng
単一マシンのインターネット アクセスの構成:
1. ネットワーク インターフェイスを用意し、ネットワーク ケーブルを接続します。
2. IP アドレスを持っている
3. ネットワーク設定を構成する
           ip (一時 IP を変更): ifconfig ethX XXXX/24 up ifconfig ens33 192.168.0.13/24 (サブネットマスク) 255.255.255.0 まで
ゲートウェイ: ルート追加デフォルト gw xxxx
DNS: vi /etc/resolv.conf ==>ネームサーバー 8.8.8.8
            テスト: www.baidu.com に ping を実行します。
            ネット統計 -anp (コンピュータのネットワーク状態を表示できます)

2. ネットワークインターフェース

1. ソケット ソケット (ファイル記述子 - 関連するネットワークデバイス) ==》BSDソケット ==》ネットワーク通信のためのインターフェース関数のセット。ソケット アピ  アプリケーションインターフェース機能インターフェース
        2. ip+ポート 住所+ポート===》このアドレスは、ホストの識別
使用されるポートアプリケーションの特定

          ポートは TCP ポート / UDP ポートに分かれており、範囲は 1 ~ 65535 です。
1000 以内のポートがシステムによって使用されることが合意されています。
http 80 www.baidu.com
                3306
テルネット 21
ssh 22

3. ネットワークバイトオーダー

        ビッグ エンディアン ストレージ (高メモリ内の低ビット - ネットワーク デバイス)
     リトルエンディアン 0x12345678 (低メモリの下位ビット - ホスト)
        12 00   
        00 12
        192.168.0.12 (ビッグエンディアン) 「最上位ビットが最初に格納される」
       12.0.168.192 (リトルエンディアン)

4. UDP (ユーザーデータグラム)

1. 特徴:リンクなし、信頼性が低い、ビッグデータ

2.フレームワーク:C/Sモード

サーバー:socket() ===>bind()===>recvfrom()===>close()
クライアント:socket() ===>bind()===>sendto() ===>close()

注:socket() のパラメータを調整する必要があります。

ソケット(PF_INET、SOCK_DGRAM、0);

      bind() client(c) はオプションですサーバー側は必須です

1.ソケット

intソケット(int ドメイン, int型, int プロトコル);
機能: プログラムがカーネルに提案します。メモリベースのソケット記述子の作成

パラメータ:ドメイン アドレス ファミリ、PF_INET == AF_INET ==>インターネット プログラム
PF_UNIX == AF_UNIX ==>スタンドアロン プログラム

          タイプソケットタイプ:
SOCK_STREAM ストリーミングソケット ===》TCP
SOCK_DGRAM ユーザー データグラム ソケット ===>UDP
SOCK_RAW 生ソケット ===》IP

          プロトコルprotocol ==》0は、アプリケーション層プロトコルに自動的に適応することを意味します。

戻り値: 正常に戻りました要求されたソケットID
失敗 -1;

2.バインド

int バインド(int ソケットファイル, 構造体sockaddr *my_addrsocklen_t アドレス);
関数: 関数がサービスターミナルと呼ばれ、パラメータ 1 に関連するファイル記述子ファイルを、パラメータ 2 で指定されたインターフェイス アドレスに関連付けることを意味します。このインターフェースからデータを受け入れます

関数が入っている場合クライアントチューン使用される場合、パラメータ 1 が配置されているディスクリプタとパラメータ 2 が配置されているインターフェース デバイスからデータが取り出される必要があることを意味します。 送った

注: クライアントの場合、この機能は省略でき、データはデフォルトのインターフェースで送信されます。
パラメータ:sockfd ファイル記述子とソケット関数を通じて以前に作成されたソケット ID
          my_addr は、物理インターフェイスの構造体ポインターです。インターフェースに関する情報を表します

struct sockaddr ユニバーサル アドレス構造体
      {
u_short sa_family;
char sa_data[14];
      };

変換されたネットワーク アドレス構造は次のとおりです。
struct _sockaddr_in ///ネットワークアドレス構造体
      {
u_short sin_family;
u_short sin_port; ///アドレスポート;
struct in_addr sin_addr; ///アドレスIP
char sin_zero[8];
      };

構造体 in_addr
      {
in_addr_t s_addr;
      }

socklen_t addrlen: パラメータ 2 の長さ。
戻り値: 成功0
失敗 -1;

3.送信引き継ぐ関数:

ssize_t 送信先(int ソケットファイル, 定数void *バッファ, size_t 長さ、整数フラグ,
                       
定数構造体 sockaddr *dest_addr, socklen_t アドレス);

機能: UDPプロトコルで相手にメッセージを送信するために使用されます。データを送る
パラメータ:sockfd ローカルソケット ID
           buff ローカル データ ストレージ (通常は送信されるデータ)
          len 送信するデータの長さ
          flags データの送信方法、0は送信をブロックすることを意味します

          dest_addr: 必須。送信先のターゲット ホスト情報構造体を示します。
        addrlen: ターゲットアドレスの長さ

戻り値:成功 送信データ長
失敗 -1;


ssize_t 受信元(int ソケットファイル, void *バッファ, size_t 長さ、 整数フラグ,
                          
構造体sockaddr *src_addr, socklen_t *アドレス長);

機能: UDP プロトコルで使用されます。得る相手から送信されたデータ。
パラメータ:sockfd ローカルソケット ID
          buff データが保存されるメモリ領域。通常は配列または動的メモリ
        len は取得するデータの長さで、通常はバッファのサイズです。
           フラグの取得方法、0ブロック

          src_addr はオプションであり、相手のアドレス情報構造体を表します。ヌル、急行相手の住所は気にしない
          addrlen 相手のアドレス情報構造体のサイズ(相手方の住所はいヌルL、それではこの値も NULL です
戻り値: 正常に受信したデータの長さ
失敗 -1;

4.閉じる

近い() ===>指定されたソケット ID を閉じます。


知らせ

1. データとデータには境界がある
2. 送信数と受信数が一致している必要があります
3.recvfrom はブロックします
4.sentoはブロックしません(recvfromは受信せず、sentoの送信には影響しません) 


   c は s を探します

サーバー.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <time.h>
  10. typedef struct sockaddr *SA;
  11. int main(int argc, char *argv[])
  12. {
  13. int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建一个UDP套接字
  14. if(-1 == sockfd) // 检查socket调用是否失败
  15. {
  16. perror("socket"); // 打印错误信息
  17. exit(1); // 退出程序
  18. }
  19. // 定义服务器地址和客户端地址结构体(尽管客户端地址通常在recvfrom中填充)
  20. struct sockaddr_in ser, cli;
  21. bzero(&ser, sizeof(ser)); // 初始化服务器地址结构体
  22. bzero(&cli, sizeof(cli)); // 初始化客户端地址结构体(但这里实际上不需要提前初始化)
  23. // 设置服务器地址结构体
  24. ser.sin_family = AF_INET;
  25. ser.sin_port = htons(50000); // 端口号转换为网络字节序
  26. ser.sin_addr.s_addr = inet_addr("192.168.203.128"); // 服务器IP地址
  27. // 将套接字绑定到服务器地址和端口
  28. int ret = bind(sockfd, (SA)&ser, sizeof(ser));
  29. if(-1 == ret)
  30. {
  31. perror("bind"); // 绑定失败时打印错误信息
  32. exit(1); // 退出程序
  33. }
  34. socklen_t len = sizeof(cli); // 用于recvfrom的客户端地址长度
  35. // 无限循环接收数据并发送响应
  36. while(1)
  37. {
  38. char buf[512] = {0}; // 准备接收数据的缓冲区
  39. // 接收数据,注意这里&len是必需的,因为recvfrom会修改它以反映实际接收到的客户端地址长度
  40. recvfrom(sockfd, buf, sizeof(buf), 0, (SA)&cli, &len);
  41. time_t tm;
  42. time(&tm); // 获取当前时间
  43. // 这里有一个问题:buf被用于接收数据,然后又被用于存储新的字符串(包括原始数据和时间戳)
  44. // 这会导致原始数据被覆盖。应该使用另一个缓冲区来存储最终的发送数据
  45. sprintf(buf, "%s %s", buf, ctime(&tm)); // 将时间戳附加到接收到的数据上
  46. // 发送数据回客户端,但注意len在这里已经被recvfrom修改,表示客户端地址的长度
  47. // 对于sendto,我们应该使用sizeof(cli)或重新初始化len
  48. sendto(sockfd, buf, strlen(buf), 0, (SA)&cli, len); // 这里使用len可能不是最佳实践
  49. }
  50. // 注意:由于程序进入了一个无限循环,下面的close和return语句实际上永远不会被执行
  51. close(sockfd); // 正常情况下应该关闭套接字
  52. return 0; // 程序正常结束
  53. }

クライアント.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <sys/types.h> /* See NOTES */
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <netinet/ip.h>
  9. #include <arpa/inet.h>
  10. #include <time.h>
  11. // 定义一个类型别名SA,指向sockaddr结构体
  12. typedef struct sockaddr *SA;
  13. // 注意:它尝试定义一个函数指针类型而不是简单的结构体指针。
  14. int main(int argc, char *argv[])
  15. {
  16. // 创建一个UDP套接字
  17. int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  18. if(-1 == sockfd)
  19. {
  20. perror("socket"); // 如果创建套接字失败,打印错误信息
  21. exit(1); // 退出程序
  22. }
  23. // 初始化sockaddr_in结构体,用于指定服务器地址和端口
  24. struct sockaddr_in ser;
  25. bzero(&ser, sizeof(ser)); // 将结构体内存清零
  26. ser.sin_family = AF_INET; // 使用IPv4地址
  27. // 将端口号从主机字节序转换为网络字节序
  28. ser.sin_port = htons(50000);
  29. // 将点分十进制的IP地址字符串转换为网络字节序的整数
  30. ser.sin_addr.s_addr = inet_addr("192.168.203.128");
  31. // 无限循环,发送数据并尝试接收响应
  32. while(1)
  33. {
  34. char buf[512] = "hello,this is udp test"; // 准备发送的数据
  35. // 发送数据到指定的服务器地址和端口
  36. sendto(sockfd, buf, strlen(buf), 0, (SA)&ser, sizeof(ser));
  37. // 清空缓冲区,准备接收数据
  38. bzero(buf, sizeof(buf));
  39. // 尝试接收数据,但源地址和端口被设置为NULL,这通常是不正确的
  40. // 在实际应用中,应该提供一个sockaddr_in结构体来接收源地址和端口信息
  41. recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
  42. // 打印接收到的数据(但在这个例子中,由于recvfrom的源地址和端口被设置为NULL,它可能不会按预期工作)
  43. printf("buf is %sn", buf);
  44. // 等待1秒后再发送下一个数据包
  45. sleep(1);
  46. }
  47. // 注意:由于程序进入了一个无限循环,下面的close和return语句实际上永远不会被执行
  48. close(sockfd); // 关闭套接字
  49. return 0; // 程序正常结束
  50. }