声明:本系列文章参考书:《TCPIP网络编程 》[韩] 尹圣雨
本人仅作笔记使用
目录
一、网络编程和套接字
二、Linux文件操作
文件描述符
打开文件
关闭文件
将数据写入文件
读取文件中的数据
三、套接字类型与协议设置
协议:计算机间对话需遵守的通信规则
创建套接字
协议族
套接字类型1:面向连接(SOCK_STREAM)
套接字类型2:面向消息(SOCK_DGRAM)
四、地址族和数据序列
IPV4的地址族ABCDE类型:
端口号:区分套接字(应用程序)
表示IPv4地址的结构体
网络字节序与地址变换
IP字符串转换为整数型
网络字节序整数型IP转换为字符串
网络编程:编写程序使得两台联网的计算机相互交换数据。
套接字:操作系统提供的软件设备,用来连接网络的工具。
直观理解:
socket:电话机
bind:分配电话号码(IP地址和端口号)
listen:连接电话线,等待来电
accpet:接电话,拿起话筒
服务端的套接字创建过程:
#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
客户端的套接字创建过程:
#include
int connect(int sockfd,struct sockaddr* serv_addr,socklen_t addrlen);
//成功返回0,失败返回-1
文件句柄。但句柄主要是Windows中的术语,Linux主要叫描述符。每当生成文件或套接字,操作系统将返回分配给它们的整数。这个整数将成为程序员与操作系统之间良好沟通的渠道。实际上,文件描述符只不过是为了方便称呼操作系统创建的文件或套接字而赋予的数而已。
直白理解:论文号相当于文件描述符,论文相当于文件或套接字。
#include
#include
#include
int open(const char *path, int flag);
path:文件名的字符串地址
flag:文件打开模式信息,若传递多个参数通过或运算(|)组合
#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:使用的协议
特点:
总结:可靠的、按序传递的、基于字节的、面向连接的数据传输方式的套接字。
100个糖果是分批传递的,但接收者凑齐100个后才装袋
也就是说接受和发送的套接字内部有缓冲,简言之字节数组,通过传输的数据保存在该数组。
因此收到数据并不意味着马上调用read函数。
有可能装满缓冲后调用1次read。
接受缓冲满了,发送端将停止传输。
int tcp_socket = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
特点:
总结:不可靠的、不按序传递的、以数据的高速传输为目的的套接字。
int udp_socket = socket(PF_INET,SOCK_DGRAM,IPPROTE_UDP);
网络地址:
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系列操作系统设立的标准。
大端序:
小端序:
网络字节序统一为大端序。
字节序转换:
unsigned short htons (unsigned short);
unsigned short ntohs (unsigned short);
unsigned long htonl (unsigned long);
unsigned long ntohl (unsigned long);
h代表主机(host)字节序,n代表网络(network)字节序
#include
in_addr_t inet_addr(const char *string);
//成功返回32位大端序整数值,失败返回INADDR_NONE
#include
int inet_aton(const char* string, struct in_addr *addr);
#include
char *inet_ntoa(struct in_addr adr);
注意,该函数返回字符串地址意味着字符串已保存到内存空间,但并未向程序员要求分配内存,而是在内部申请内存并保存了字符串。
也就是说,调用完该函数,需要立即字符串复制到其他内存空间。