TCP/IP 网络编程(一):基础知识

声明:本系列文章参考书:《TCPIP网络编程 》[韩] 尹圣雨 

本人仅作笔记使用

目录

一、网络编程和套接字

二、Linux文件操作

文件描述符

打开文件

关闭文件

将数据写入文件

读取文件中的数据

三、套接字类型与协议设置

协议:计算机间对话需遵守的通信规则

创建套接字

协议族

套接字类型1:面向连接(SOCK_STREAM)

套接字类型2:面向消息(SOCK_DGRAM)

四、地址族和数据序列

IPV4的地址族ABCDE类型:

端口号:区分套接字(应用程序)

表示IPv4地址的结构体

网络字节序与地址变换

IP字符串转换为整数型

网络字节序整数型IP转换为字符串


一、网络编程和套接字

网络编程:编写程序使得两台联网的计算机相互交换数据。

套接字:操作系统提供的软件设备,用来连接网络的工具。

直观理解:

socket:电话机

bind:分配电话号码(IP地址和端口号)

listen:连接电话线,等待来电

accpet:接电话,拿起话筒

服务端的套接字创建过程:

  • 调用socket创建套接字
  • 调用bind分配IP地址和端口好
  • 调用listen转为可接受请求状态
  • 调用accept受理连接请求
#include 
int socket(int domain,int type,int protocol);
int bind(int sockfd,struct sockaddr *myaddr,socklen_t addrlen);
int listen(int sockfd,int backlog);
int accept(int sockfd,struct sockaddr*,socklen_T *addrlen);
//成功返回0,失败返回-1

客户端的套接字创建过程:

  • 调用socket创建套接字
  • 调用connect向服务器发送连接请求
#include 
int connect(int sockfd,struct sockaddr* serv_addr,socklen_t addrlen);
//成功返回0,失败返回-1

二、Linux文件操作

文件描述符

文件句柄。但句柄主要是Windows中的术语,Linux主要叫描述符。每当生成文件或套接字,操作系统将返回分配给它们的整数。这个整数将成为程序员与操作系统之间良好沟通的渠道。实际上,文件描述符只不过是为了方便称呼操作系统创建的文件或套接字而赋予的数而已。

直白理解:论文号相当于文件描述符论文相当于文件或套接字

打开文件

#include 
#include 
#include 

int open(const char *path, int flag);

path:文件名的字符串地址

flag:文件打开模式信息,若传递多个参数通过或运算(|)组合

TCP/IP 网络编程(一):基础知识_第1张图片

关闭文件

#include 
int close(int fd);

fd:需要关闭的文件或套接字的文件描述符

Linux操作系统不区分与套接字,此函数不仅可以关闭文件,也可以关闭套接字

将数据写入文件

向文件输出(传输)数据。

#include 
ssize_t write(int fd, const void* buf, size_t nbytes);

fd:数据传输对象的文件描述符

buf:要传输数据的缓冲地址值

nbytes:传输数据的字节数

(注:size_t为unsigned int类型,ssize_t为signed,同时操作系统为了与程序员的代码区分加了后缀_t)

读取文件中的数据

输入(接受)数据

#include 
ssize_t read(int fd, void *buf, size_t nbytes);

fd:数据接收对象文件描述符

buf:接收数据缓冲地址值

nbytes:接收数据最大字节数

三、套接字类型与协议设置

协议:计算机间对话需遵守的通信规则

创建套接字

#include 
int socket(int domain, int type, int protocol);

domain:套接字中使用的协议族

type:套接字数据类型

protocol:使用的协议

协议族

TCP/IP 网络编程(一):基础知识_第2张图片

套接字类型1:面向连接(SOCK_STREAM)

特点:

  • 传输过程中数据不会丢失
  • 按序传输
  • 传输的数据不存在数据边界
  • 套接字必须一一对应

总结:可靠的按序传递的基于字节的面向连接的数据传输方式的套接字。

TCP/IP 网络编程(一):基础知识_第3张图片

100个糖果是分批传递的,但接收者凑齐100个后才装袋

也就是说接受和发送的套接字内部有缓冲,简言之字节数组,通过传输的数据保存在该数组。

因此收到数据并不意味着马上调用read函数。

有可能装满缓冲后调用1次read。

接受缓冲满了,发送端将停止传输。

int tcp_socket = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

套接字类型2:面向消息(SOCK_DGRAM)

特点:

  • 强调快速传输而非传输顺序
  • 传输的数据可能丢失也可能损毁
  • 传输的数据有数据边界
  • 限制每次传输的数据大小

TCP/IP 网络编程(一):基础知识_第4张图片

总结:不可靠的不按序传递的以数据的高速传输为目的的套接字。

int udp_socket = socket(PF_INET,SOCK_DGRAM,IPPROTE_UDP);

四、地址族和数据序列

网络地址:

  • IPV4:4字节地址族
  • IPV6:16字节地址族

IPV4的地址族ABCDE类型:

TCP/IP 网络编程(一):基础知识_第5张图片

  • A类地址首字节范围:0-127(首位从0开始)
  • B类地址首字节范围:128-191(首位从10开始)
  • C类地址首字节范围:192-223(首位从110开始)

端口号:区分套接字(应用程序)

  • NIC(Network Interface Card,网卡)
  • 端口号不能重复,但TCP和UDP可以使用同一个端口

表示IPv4地址的结构体

struct sockaddr_in{
    sa_family_t     sin_family;  //地址族
    uint16_t        sin_port;    //16位TCP/UDP端口号
    struct in_addr  sin_addr;    //32位IP地址
    char            sin_zero[8]; //不适用
};

struct in_addr{
    In_addr_t     s_addr;//32位IPv4地址
};

初始化:

struct sockaddr_in addr;
char *serv_ip = "211.217.168.13";
char *serv_port = "9190";
memset(&addr, 0 ,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(serv_ip);
addr.sin_port = htons(atoi(serv_port));

POSIX(Portable Operating System Interface,可以指操作系统接口),为UNIX系列操作系统设立的标准。

TCP/IP 网络编程(一):基础知识_第6张图片

网络字节序与地址变换

大端序:

TCP/IP 网络编程(一):基础知识_第7张图片

小端序:

TCP/IP 网络编程(一):基础知识_第8张图片

网络字节序统一为大端序。

字节序转换:

unsigned short htons (unsigned short);
unsigned short ntohs (unsigned short);
unsigned long  htonl (unsigned long);
unsigned long  ntohl (unsigned long);

h代表主机(host)字节序,n代表网络(network)字节序 

IP字符串转换为整数型

#include 
in_addr_t inet_addr(const char *string);
//成功返回32位大端序整数值,失败返回INADDR_NONE
#include 
int inet_aton(const char* string, struct in_addr *addr);

网络字节序整数型IP转换为字符串

#include 
char *inet_ntoa(struct in_addr adr);

 注意,该函数返回字符串地址意味着字符串已保存到内存空间,但并未向程序员要求分配内存,而是在内部申请内存并保存了字符串。

也就是说,调用完该函数,需要立即字符串复制到其他内存空间。

你可能感兴趣的:(网络/系统编程,网络,tcp/ip,linux)