기술나눔

네트워크 프로그래밍: 기본 개념

2024-07-12

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

1. OSI 모델

OSI 모델 ===》개방형 시스템 상호 연결 모델 ==》7개 계층으로 구분됩니다.
이상형 ==》아직 실현되지 않음
TFTP로 전송
b /etc/passwd
/etc/123 입니다
애플리케이션 레이어
프리젠테이션 계층 암호화 및 복호화 gzip
세션 레이어 네트워크 연결 끊김, 연결 상태, Keep-Close Keep-Alive

전송 계층 tcp udp 프로토콜 파일 비디오, 오디오
네트워크 계층 IP NAT

링크 레이어 전환 데이터 포맷 프레임 확인
물리 계층 100Mb/8Gbits 100MB 동축 케이블 10Gb 2.4G 5G

아래에서 위로, 아래가 가장 기본

2. TCP/IP 모델

TCP/IP 모델 ==》인터넷 모델 ==》4개의 레이어로 나뉩니다:
실제 모델 ===》산업 표준
TCP/IP 프로토콜 스택
응용 계층 ====》응용
전송 계층 ====》포트 번호 tcp udp (어떤 전송 방법이 사용되는지,신뢰할 수 있는 TCPUDP는 실시간 성능이 뛰어납니다.
네트워크 계층 ====》IP 주소(상대방과 호스트를 찾는 방법
인터페이스 레이어 ====》네트워크 카드 드라이버 1GB
피캡,,,

3. TCP/IP 프로토콜 제품군

www.taobao.com ---> 192.168.0.19
www.voa.com VPN
DNS 도메인 이름 확인(일반적으로 주를 기준으로 함)


DHCP(동적 호스트 구성 프로토콜)
애플리케이션 계층:HTTP(웹페이지) TFTP(간단한 단거리 파일 전송)FTP(인터넷 장거리 전송)
                   SNMP(네트워크 장치, 시스템 및 애플리케이션 관리 및 모니터링)DNS...
전송 계층: TCP UDP 56k 고양이
네트워크 계층: IP ICMP(ping) RIP OSPF IGMP...
인터페이스 계층: ARP(주소 확인 프로토콜) RARP... ip--->mac
아르프,,,,
    192.160.0.112 


1. 네트워크 기본

네트워크 기본 ===》ABCDE 클래스
010  3333344444
IP 주소 == 네트워크 비트 + 호스트 비트

IP 주소 분류: 점분리 십진수 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만, 한 사람이 보내고, 모두가 받음)
        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 주소의 처음 세 그룹은 네트워크 주소이고 네 번째 그룹은 호스트 주소입니다.
바이너리의 가장 높은 비트는 다음과 같아야 합니다: 110xxxxx로 시작
소수 표현 범위: 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 주소.
  
  수도 빔/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
            테스트: ping www.baidu.com
            그물통계 -anp(컴퓨터의 네트워크 상태를 볼 수 있음)

2. 네트워크 인터페이스

1. 소켓 소켓(파일 설명자 - 연결된 네트워크 장치) ==》BSD 소켓 ==》네트워크 통신을 위한 인터페이스 기능 세트.소켓 아피  애플리케이션 인터페이스기능 인터페이스
        2. 아이피+포트 주소+포트===》주소는 다음과 같습니다.호스트 식별
사용된 포트애플리케이션 식별

          포트는 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 모드

서버:소켓() ===>바인드()===>recvfrom()===>닫기()
클라이언트:소켓() ===>바인드()===>송신() ===>닫기()

참고: 소켓()의 매개변수를 조정해야 합니다.

소켓(PF_INET,SOCK_DGRAM,0);

      바인딩() 클라이언트(c)는 선택 사항입니다.서버측이 필요합니다.

1.소켓

int 소켓(int 도메인, int형, int 프로토콜);
기능: 프로그램이 커널에 제안합니다.메모리 기반 소켓 설명자 만들기

매개변수:도메인 주소 계열, PF_INET == AF_INET ==>인터넷 프로그램
PF_UNIX == AF_UNIX ==>독립형 프로그램

          유형 소켓 유형:
SOCK_STREAM 스트리밍 소켓 ===》TCP
SOCK_DGRAM 사용자 데이터그램 소켓 ===>UDP
SOCK_RAW 원시 소켓 ===》IP

          프로토콜 프로토콜 ==》0은 애플리케이션 계층 프로토콜에 자동으로 적응함을 의미합니다.

반환 값: 성공적으로 반환되었습니다.요청된 소켓 ID
실패 -1;

2. 묶다

int 바인드(int sockfd, 구조체 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 sockfd, 상수 void *buf, 크기_t 길이,int 플래그,
                       
const 구조체 sockaddr *dest_addr, socklen_t 주소);

기능: UDP 프로토콜로 상대방에게 메시지를 보내는 데 사용됩니다.데이터를 보내다
매개변수:sockfd 로컬 소켓 ID
           로컬 데이터 저장소 강화, 일반적으로 전송할 데이터
          전송할 데이터의 len 길이
          플래그 데이터를 보내는 방법,0은 전송 차단을 의미합니다.

          dest_addr: 필수, 전송할 대상 호스트 정보 구조를 나타냅니다.
        addrlen: 대상 주소 길이

반환 값: 성공 전송된 데이터 길이
실패 -1;


ssize_t 수신(int sockfd, 무효 *버프, 크기_t 길이, int 플래그,
                          
구조체 sockaddr *src_addr, socklen_t *추가);

기능: UDP 프로토콜에 사용됨얻다상대방이 보낸 데이터입니다.
매개변수:sockfd 로컬 소켓 ID
          buff 데이터가 저장될 메모리 영역, 일반적으로 배열 또는 동적 메모리
        len은 획득할 데이터의 길이이며 일반적으로 버프의 크기입니다.
           플래그 획득 방법,0 차단

          src_addr은 선택사항이며 상대방의 주소 정보 구조를 나타냅니다.없는,표현하다상대방 주소는 신경쓰지 마세요
          addrlen 상대방의 주소 정보 구조의 크기,상대방의 주소없음엘, 그럼이 값도 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. }