Linux网络编程(1):套接字编程简介

        这几天借了一本网络编程的经典书籍:《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开放此端口。


你可能感兴趣的:(Linux网络编程)