Linux 下Socket编程基础.docx
- 文档编号:2875704
- 上传时间:2022-11-16
- 格式:DOCX
- 页数:9
- 大小:23.34KB
Linux 下Socket编程基础.docx
《Linux 下Socket编程基础.docx》由会员分享,可在线阅读,更多相关《Linux 下Socket编程基础.docx(9页珍藏版)》请在冰豆网上搜索。
Linux下Socket编程基础
Linux下Socket编程基础
1、 引言
Linux的兴起可以说是Internet创造的一个奇迹。
Linux作为一个完全开放其原代码的免费的自由软件,兼容了各种UNIX标准(如POSIX、UNIX System V 和 BSD UNIX 等)的多用户、多任务的具有复杂内核的操作系统。
在中国,随着Internet的普及,一批主要以高等院校的学生和ISP的技术人员组成的Linux爱好者队伍已经蓬勃成长起来。
越来越多的编程爱好者也逐渐酷爱上这个优秀的自由软件。
本文介绍了Linux下Socket的基本概念和函数调用。
2、 什么是Socket
Socket(套接字)是通过标准的UNIX文件描述符和其它程序通讯的一个方法。
每一个套接字都用一个半相关描述:
{协议,本地地址、本地端口}来表示;一个完整的套接字则用一个相关描述:
{协议,本地地址、本地端口、远程地址、远程端口},每一个套接字都有一个本地的由操作系统分配的唯一的套接字号。
3、 Socket的三种类型
(1) 流式Socket(SOCK_STREAM)
流式套接字提供可靠的、面向连接的通信流;它使用TCP协议,从而保证了数据传输的正确性和顺序的。
(2) 数据报Socket(SOCK_DGRAM)
数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠、无差错。
它使用数据报协议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一样大小
};
(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里
7、 IP地址转换
有三个函数将数字点形式表示的字符串IP地址与32位网络字节顺序的二进制形式的IP地址进行转换
(1) unsigned long int inet_addr(const char * cp):
该函数把一个用数字和点表示的IP地址的字符串转换成一个无符号长整型,如:
struct sockaddr_in ina
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开头的函数有:
(1) void bzero(void * s,int n):
将参数s指定的内存的前n个字节设置为0,通常它用来将套接字地址清0。
(2) void bcopy(const void * src,void * dest,int n):
从参数src指定的内存区域拷贝指定数目的字节内容到参数dest指定的内存区域。
(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 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>
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次握手过程。
在建立连接之后或发生错误时函数返回。
连接过程可能出现的错误情况有:
(1) 如果客户机TCP协议没有接收到对它的SYN数据段的确认,函数以错误返回,错误类型为ETIMEOUT。
通常TCP协议在发送SYN数据段失败之后,会多次发送SYN数据段,在所有的发送都高中失败之后,函数以错误返回。
注:
SYN(synchronize)位:
请求连接。
TCP用这种数据段向对方TCP协议请求建立连接。
在这个数据段中,TCP协议将它选择的初始序列号通知对方,并且与对方协议协商最大数据段大小。
SYN数据段的序列号为初始序列号,这个SYN数据段能够被确认。
当协议接收到对这个数据段的确认之后,建立TCP连接。
(2) 如果远程TCP协议返回一个RST数据段,函数立即以错误返回,错误类型为ECONNREFUSED。
当远程机器在SYN数据段指定的目的端口号处没有服务进程在等待连接时,远程机器的TCP协议将发送一个RST数据段,向客户机报告这个错误。
客户机的TCP协议在接收到RST数据段后不再继续发送SYN数据段,函数立即以错误返回。
注:
RST(reset)位:
表示请求重置连接。
当TCP协议接收到一个不能处理的数据段时,向对方TCP协议发送这种数据段,表示这个数据段所标识的连接出现了某种错误,请求TCP协议将这个连接清除。
有3种情况可能导致TCP协议发送RST数据段:
(1)SYN数据段指定的目的端口处没有接收进程在等待;
(2)TCP协议想放弃一个已经存在的连接;(3)TCP接收到一个数据段,但是这个数据段所标识的连接不存在。
接收到RST数据段的TCP协议立即将这条连接非正常地断开,并向应用程序报告错误。
(3) 如果客户机的SYN数据段导致某个路由器产生“目的地不可到达”类型的ICMP消息,函数以错误返回
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux 下Socket编程基础 Socket 编程 基础