linux socket编程基础(必读)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
7、 IP 地址转换 有三个函数将数字点形式表示的字符串 IP 地址与32位网络字节顺序的二进 制形式的 IP 地址进行转换 (1) unsigned long int inet_addr(const char * cp):该函数把一个用数字和 点表示的 IP 地址的字符串转换成一个无符号长整型,如:struct sockaddr_in ina
(2) 如果远程 TCP 协议返回一个 RST 数据段,函数立即以错误返回,错 误类型为 ECONNREFUSED。当远程机器在 SYN 数据段指定的目的端口号处
没有服务进程在等待连接时,远程机器的 TCP 协议将发送一个 RST 数据段,向 客户机报告这个错误。客户机的 TCP 协议在接收到 RST 数据段后不再继续发送 SYN 数据段,函数立即以错误返回。
(3) int bcmp(const void * s1,const void * s2,int n):比较参数 s1指 定的内存区域和参数 s2指定的内存区域的前 n 个字节内容,如果相同则返回0, 否则返回非0。
注:以上函数的原型定义在 strings.h 中。 以 mem 开头的函数有: (1) void * memset(void * s,int c,size_t n):将参数 s 指定的内存区 域的前 n 个字节设置为参数 c 的内容。 (2) void * memcpy(void * dest,const void * src,size_t n):功能同 bcopy (),区别:函数 bcopy()能处理参数 src 和参数 dest 所指定的区域有重叠的 情况,memcpy()则不能。 (4) int memcmp(const void * s1,const void * s2,size_t n):比较参 数 s1和参数 s2指定区域的前 n 个字节内容,如果相同则返回0,否则返回非0。 注:以上函数的原型定义在 string.h 中。 9、 基本套接字函数 (1) socket() #include<sys/types.h> #include<sys/socket.h>
int connect(int sockfd,struct sockaddr * servaddr,int addrlen)
参数 sockfd 是函数 socket 返回的套接字描述符;参数 servaddr 指定远程服 务器的套接字地址,包括服务器的 IP 地址和端口号;参数 addrlen 指定这个套 接字地址的长度。成功时返回0,否则返回-1,并设置全局变量为以下任何一种 错误类型:ETIMEOUT、ECONNREFUSED、EHOSTUNREACH 或 ENETUNREACH。
在调用函数 connect 之前,客户机需要指定服务器进程的套接字地址。客户 机一般不需要指定自己的套接字地址(IP 地址和端口号),系统会自动从1024 至5000的端口号范围内为它选择一个未用的端口号,然后以这个端口号和本机 的 IP 地址填充这个套接字地址。
客户机调用函数 connect 来主动建立连接。这个函数将启动 TCP 协议的3次 握手过程。在建立连接之后或发生错误时函数返回。连接过程可能出现的错误情 况有:
2、 什么是 Socket Socket(套接字)是通过标准的 UNIX 文件描述符和其它程序通讯的一个方 法。每一个套接字都用一个半相关描述:{协议,本地地址、本地端口}来表示; 一个完整的套接字则用一个相关描述:{协议,本地地址、本地端口、远程地址、 远程端口},每一个套接字都有一个本地的由操作系统分配的唯一的套接字号。 3、 Socket 的三种类型 (1) 流式 Socket(SOCK_STREAM) 流式套接字提供可靠的、面向连接的通信流;它使用 TCP 协议,从而保证 了数据传输的正确性和顺序的。 (2) 数据报 Socket(SOCK_DGRAM)
socket 编程 Linux 下 Socket 编程基础 (实例)
1、 引言
Linux 的兴起可以说是 Internet 创造的一个奇迹。Linux 作为一个完全开放其原 代码的免费的自由软件,兼容了各种 UNIX 标准(如 POSIX、UNIX System V 和 BSD UNIX 等)的多用户、多任务的具有复杂内核的操作系统。在中国,随着 Internet 的普及,一批主要以高等院校的学生和 ISP 的技术人员组成的 Linux 爱 好者队伍已经蓬勃成长起来。越来越多的编程爱好者也逐渐酷爱上这个优秀的自 由软件。本文介绍了 Linux 下 Socket 的基本概念和函数调用。
(3) struct in_addr{ unsigned long s_addr; }; 6、 网络字节顺序及其转换函数 (1) 网络字节顺序 每一台机器内部对变量的字节存储顺序不同,而网络传输的数据是一定要统 一顺序的。所以对内部字节表示顺序与网络字节顺序不同的机器,一定要对数据 进行转换,从程序的可移植性要求来讲,就算本机的内部字节表示顺序与网络字 节顺序相同也应该在传输数据以前先调用数据转换函数,以便程序移植到其它机 器上后能正确执行。真正转换还是不转换是由系统函数自己来决定的。 (2) 有关的转换函数 * unsigned short int htons(unsigned short int hostshort): 主机字节顺序转换成网络字节顺序,对无符号短型进行操作4bytes * unsigned long int htonl(unsigned long int hostlong): 主机字节顺序转换成网络字节顺序,对无符号长型进行操作8bytes * unsigned short int ntohs(unsigned short int netshort): 网络字节顺序转换成主机字节顺序,对无符号短型进行操作4bytes * unsigned long int ntohl(unsigned long int netlong): 网络字节顺序转换成主机字节顺序,对无符号长型进行操作8bytes 注:以上函数原型定义在 netinet/in.h 里
注:RST(reset)位:表示请求重置连接。当 TCP 协议接收到一个不能处 理的数据段时,向对方 TCP 协议发送这种数据段,表示这个数据段所标识的连 接出现了某种错误,请求 TCP 协议将这个连接清除。有3种情况可能导致 TCP 协议发送 RST 数据段:(1)SYN 数据段指定的目的端口处没有接收进程在等待; (2)TCP 协议想放弃一个已经存在的连接;(3)TCP 接收到一个数据段,但 是这个数据段所标识的连接不存在。接收到 RST 数据段的 TCP 协议立即将这条 连接非正常地断开,并向应用程序报告错误。
(1) 如果客户机 TCP 协议没有接收到对它的 SYN 数据段的确认,函数以 错误返回,错误类型为 ETIMEOUT。通常 TCP 协议在发送 SYN 数据段失败之 后,会多次发送 SYN 数据段,在所有的发送都高中失败之后,函数以错误返回。
注:SYN(synchronize)位:请求连接。TCP 用这种数据段向对方 TCP 协 议请求建立连接。在这个数据段中,TCP 协议将它选择的初始序列号通知对方, 并且与对方协议协商最大数据段大小。SYN 数据段的序列号为初始序列号,这 个 SYN 数据段能够被确认。当协议接收到对这个数据段的确认之后,建立 TCP 连接。
(1) void bzero(void * s,int n):将参数 s 指定的内存的前 n 个字节设置 为0,通常它用来将套接字地址清0。
(2) void bcopy(const void * src,void * dest,int n):从参数 src 指定 的内存区域拷贝指定数目的字节内容到参数 dest 指定的内存区域。
ina.sin_addr.s_addr=inet_addr("202.206.17.101") 该函数成功时:返回转换结果;失败时返回常量 INADDR_NONE,该常量 =-1,二进制的无符号整数-1相当于255.255.255.255,这是一个广播地址,所以 在程序中调用 iner_addr()时,一定要人为地对调用失败进行处理。由于该函 数不能处理广播地址,所以在程序中应该使用函数 inet_aton()。 (2)int inet_aton(const char * cp,struct in_addr * inp):此函数将字符串 形式的 IP 地址转换成二进制形式的 IP 地址;成功时返回1,否则返回0,转换后 的 IP 地址存储在参数 inp 中。 (3) char * inet_ntoa(struct in-addr in):将32位二进制形式的 IP 地址转 换为数字点形式的 IP 地址,结果在函数返回值中返回,返回的是一个指向字符 串的指针。 8、 字节处理函数 Socket 地址是多字节数据,不是以空字符结尾的,这和 C 语言中的字符串 是不同的。Linux 提供了两组函数来处理多字节数据,一组以 b(byte)开头, 是和 BSD 系统兼容的函数,另一组以 mem(内存)开头,是 ANSI C 提供的函 数。 以 b 开头的函数有:
Leabharlann Baidu
int socket(int domain,int type,int protocol) 参数 domain 指定要创建的套接字的协议族,可以是如下值: AF_UNIX //UNIX 域协议族,本机的进程间通讯时使用 AF_INET //Internet 协议族(TCP/IP) AF_ISO //ISO 协议族 参数 type 指定套接字类型,可以是如下值: SOCK_STREAM //流套接字,面向连接的和可靠的通信类型 SOCK_DGRAM //数据报套接字,非面向连接的和不可靠的通信类型 SOCK_RAW //原始套接字,只对 Internet 协议有效,可以用来直接访问 IP 协议 参数 protocol 通常设置成0,表示使用默认协议,如 Internet 协议族的流套 接字使用 TCP 协议,而数据报套接字使用 UDP 协议。当套接字是原始套接字 类型时,需要指定参数 protocol,因为原始套接字对多种协议有效,如 ICMP 和 IGMP 等。 Linux 系统中创建一个套接字的操作主要是:在内核中创建一个套接字数据 结构,然后返回一个套接字描述符标识这个套接字数据结构。这个套接字数据结 构包含连接的各种信息,如对方地址、TCP 状态以及发送和接收缓冲区等等, TCP 协议根据这个套接字数据结构的内容来控制这条连接。 (2) 函数 connect() #include<sys/types.h> #include<sys/socket.h>
数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传 输,是无序的,并且不保证可靠、无差错。它使用数据报协议 UDP
(3) 原始 Socket 原始套接字允许对底层协议如 IP 或 ICMP 直接访问,它功能强大但使用较 为不便,主要用于一些协议的开发。 4、 利用套接字发送数据 1、 对于流式套接字用系统调用 send()来发送数据。 2、 对于数据报套接字,则需要自己先加一个信息头,然后调用 sendto() 函数把数据发送出去。 5、 Linux 中 Socket 的数据结构 (1) struct sockaddr { //用于存储套接字地址 unsigned short sa_family;//地址类型 char sa_data[14]; //14字节的协议地址 }; (2) struct sockaddr_in{ //in 代表 internet short int sin_family; //internet 协议族 unsigned short int sin_port;//端口号,必须是网络字节顺序 struct in_addr sin_addr;//internet 地址,必须是网络字节顺序 unsigned char sin_zero;//添0(和 struct sockaddr 一样大小 };