这几天借了一本网络编程的经典书籍:《UNIX网络编程(卷一:套接字联网API)》,想着学习一下网络编程。下面的内容主要依靠这本书籍,然后,结合我自己的知识和网络资源,对Linux网络编程做由浅入深的学习。
1、什么是套接字(Socket)?
我自己的理解是:套接字,即端点、端口,是建立在应用层和传输层之间的一个概念。
网络释义:套接字,是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。为了区别不同的应用进程和连接,许多计算机操作系统为应用进程与TCP/IP协议交互提供了“套接字接口”,以便区分不同应用进程间的网络通信和连接。2、套接字的分类
(1)流式套接字:SOCK_STREAM;用于提供面向连接、可靠的数据传输服务,使用了传输控制协议,即TCP协议。(2)数据包套接字:SOCK_DGRAM;用于提供了一种无连接的服务,使用UDP(User Datagram Protocol)协议进行数据的传输。
(3)原始套接字:SOCK_RAW;原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议发送数据必须使用原始套接字。
3、常用结构体和地址转换函数
1、通用套接字地址结构:struct sockaddr
- struct sockaddr
- {
- unsigned short sa_family;
- char sa_data[14];
- }
2、Internet下套接字地址结构:struct sockaddr_in
- struct sockaddr_in
- {
- shortsin_family; //通信协议族,AF_INET、AF_UNIX
- unsigned short sin_port;//通信端口
- struct in_addrsin_addr;//IP地址
- unsigned charsin_zero[8];
- }
其中:
- struct in_addr //32位IP地址
- {
- unsigned long s_addr;
- }
struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,二者长度一样,都是16个字节。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。一般情况下,需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中。
3、地址转换函数
BSD网络软件中包含了两个函数,用来在二进制地址格式(网络字节序)和点分十进制字符串格式之间相互转换,但是这两个函数仅仅支持IPv4。
- in_addr_t inet_addr(const char *cp);//返回32位二进制网络字节序的IPv4地址
- int inet_aton(const char* strptr, struct in_addr *addrptr); //将strptr所指向的字符串转换成一个32位的网络字节序二进制值,并通过指针addrptr来存储
- char * inet_ntoa(struct in_addr in);//返回指向一个点分十进制数串的指针,其中n表示32位网络字节序的IP地址,a表示点分十进制字符串
功能相似的两个函数同时支持IPv4和IPv6
- const char * inet_ntop(int domain, const void *addr, char *str, socklen_t size);
- int inet_pton(int domain, const char *str, void *addr);//将str所值的字符串转换成一个32位网络字节序二进制值,并通过指针addrptr来存储
例:
- struct sockaddr_in servaddr;
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(8008);
- inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
4、主机字节序、网络字节序和字节转换函数
主机字节序就是我们平常说的大端和小端模式,不同的 CPU 有不同的字节序类型,这些字节序是指整数在内存中保存的顺序 。最常见的有两种:1. Little endian:将低序字节存储在起始地址
2. Big endian:将高序字节存储在起始地址
例子:在内存中双字0x01020304(DWORD)的存储方式
内存地址
4000 4001 4002 4003
LE 04 03 02 01
BE 01 02 03 04
网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。
为了进行两者之间的转换,socket提供了转换的函数 有下面四个字节转换函数:
htons() :把unsigned short类型从主机序转换到网络序
htonl () :把unsigned long类型从主机序转换到网络序
ntohs() :把unsigned short类型从网络序转换到主机序
ntohl () :把unsigned long类型从网络序转换到主机序
另外,我们要知道,16位端口号(一个整形数字),32位IPv4地址(四个整形数字)。
通常的用法是:- #define MYPORT 8008
- int sockfd;
- struct sockaddr_in my_addr;
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- my_addr.sin_family = AF_INET; /* 主机字节序 */
- my_addr.sin_addr.s_addr = inet_addr("192.168.0.1");
- my_addr.sin_port = htons(MYPORT); /* short, 网络字节序 */
- bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */
- //memset(&my_addr.sin_zero, 0, 8);
- bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
5、常用端口号
端口:21
服务:FTP说明:FTP服务器所开放的端口,用于上传、下载。最常见的攻击者用于寻找打开anonymous的FTP服务器的方法。这些服务器带有可读写的目录。木马Doly Trojan、Fore、Invisible FTP、WebEx、WinCrash和Blade Runner所开放的端口。
端口:22
服务:Ssh
说明:PcAnywhere建立的TCP和这一端口的连接可能是为了寻找ssh。这一服务有许多弱点,如果配置成特定的模式,许多使用RSAREF库的版本就会有不少的漏洞存在。
端口:23
服务:Telnet
说明:远程登录,入侵者在搜索远程登录UNIX的服务。大多数情况下扫描这一端口是为了找到机器运行的操作系统。还有使用其他技术,入侵者也会找到密码。木马Tiny Telnet Server就开放这个端口。
端口:25
服务:SMTP
说明:SMTP服务器所开放的端口,用于发送邮件。入侵者寻找SMTP服务器是为了传递他们的SPAM。入侵者的帐户被关闭,他们需要连接到高带宽的E-MAIL服务器上,将简单的信息传递到不同的地址。木马Antigen、Email Password Sender、Haebu Coceda、Shtrilitz Stealth、WinPC、WinSpy都开放这个端口。
端口:53
服务:Domain Name Server(DNS)
说明:DNS服务器所开放的端口,入侵者可能是试图进行区域传递(TCP),欺骗DNS(UDP)或隐藏其他的通信。因此防火墙常常过滤或记录此端口。
端口:80
服务:HTTP
说明:用于网页浏览。木马Executor开放此端口。