Linux 网络编程实例详解
本文介绍了在 Linux 环境下的 socket 编程常用函数用法及 socket 编程的一般规则和客户/服务器
模型的编程应注意的事项和常遇问题的解决方法,并举了具体代 码实例。要理解本文所谈的技
术问题需要读者具有一定 C 语言的编程经验和 TCP/IP 方面的基本知识。要实习本文的示例,需
要 Linux 下的 gcc 编译平台支持。
Socket 定义
网络的 Socket 数据传输是一种特殊的 I/O,Socket 也是一种文件描述符。Socket 也具有一
个类似于打开文件的函数调用—Socket(),该函数返回一个整型的 Socket 描述符,随后的连接建
立、数据传输等操作都是通过该 Socket 实现的。常用 的 Socket 类型有两种:流式 Socket—
SOCK_STREAM 和数据报式 Socket—SOCK_DGRAM。流式是一种面向连接的 Socket,针对于
面向连接的 TCP 服务应用;数据报式 Socket 是一种无连接的 Socket,对应于无连接的 UDP 服
务应用。
Socket 编程相关数据类型定义
计算机数据存储有两种字节优先顺序:高位字节优先和低位字节优先。Intenet 上数据以高位
字节优先顺序在网络上传输,所以对于在内部是以低位字节优先方式存储数据的机器,在
Internet 上传输数据时就需要进行转换。
我们要讨论的第一个结构类型是:struct sockaddr,该类型是用来保存 socket 信息的:
struct sockaddr {
unsigned short sa_family; /* 地址族, AF_xxx */
char sa_data[14]; /* 14 字节的协议地址 */ };
sa_family 一般为 AF_INET;sa_data 则包含该 socket 的 IP 地址和端口号。
另外还有一种结构类型:
struct sockaddr_in {
short int sin_family; /* 地址族 */
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* IP 地址 */
unsigned char sin_zero[8]; /* 填充 0 以保持与 struct sockaddr 同样大
小 */
};
这个结构使用更为方便。sin_zero(它用来将 sockaddr_in 结构填充到与 struct sockaddr 同样
的长度)应该用 bzero()或 memset()函数将其置为零。指向 sockaddr_in 的指针和指向 sockaddr 的
指针可以相互转换,这意味着如果一个函数所需参数类型是 sockaddr 时,你可以在函数调用的
时候将一个指向 sockaddr_in 的指针转换为指向 sockaddr 的指针;或者相反。sin_family 通常被
赋 AF_INET;in_port 和 sin_addr 应该转换成为网络字节优先顺序;而 sin_addr 则不需要转换。
我们下面讨论几个字节顺序转换函数:
htons()--"Host to Network Short" ; htonl()--"Host to Network long"
ntohs()--"Network to Host Short" ; ntohl()--"Network to Host Long"
在这里, h 表示"host" ,n 表示"network",s 表示"short",l 表示 "long"
。
打开 socket 描述符、建立绑定并建立连接
socket 函数原型为:
int socket(int domain, int type, int protocol);
domain 参 数 指 定 socket 的 类 型 : SOCK_STREAM 或 SOCK_DGRAM ; protocol 通 常 赋 值