socket编程在windows和linux下的区别是啥?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了socket编程在windows和linux下的区别是啥?相关的知识,希望对你有一定的参考价值。
参考技术A1. 头文件
windows下winsock.h或winsock2.h
linux下netinet/in.h(大部分都在这儿),unistd.h(close函数在这儿),sys/socket.h(在in.h里已经包含了,可以省了)
2. 初始化
windows下需要用WSAStartup启动Ws2_32.lib,并且要用#pragma comment(lib,"Ws2_32")来告知编译器链接该lib。
linux下不需要
3. 关闭socket
windows下closesocket(...)
linux下close(...)
4. 类型
windows下SOCKET
linux下int
5. 获取错误码
windows下getlasterror()/WSAGetLastError()
linux下,未能成功执行的socket操作会返回-1;如果包含了errno.h,就会设置errno变量
6. 设置非阻塞
windows下ioctlsocket()
linux下fcntl(),需要头文件fcntl.h
7. send函数最后一个参数
windows下一般设置为0
linux下最好设置为MSG_NOSIGNAL,如果不设置,在发送出错后有可能会导致程序退出
8. 毫秒级时间获取
windows下GetTickCount()
linux下gettimeofday()
Windows 环境下的 Socket 编程 2 - 地址族与数据序列
地址族
在《Windows 环境下的 Socket 编程 1 - 环境搭建和 Socket 相关函数》这篇文章中,提到过 socket
函数,其原型为:
/*成功返回 SOCKET 句柄,失败返回 INVALID_SOCKET*/
SOCKET socket(int af,int type,int protocol);
其中第一个参数 af
用于指定 SOCKET 使用的 协议族
,常见协议族有:IPv4 协议族(PF_INET
)、IPv6 协议族(PF_INET6
)等。
本节重点在于 IPv4 协议族的地址信息表示。
协议族的地址信息使用结构体 struct sockaddr
表示。
bind
函数、 accept
函数、connect
函数都要求传入 struct sockaddr
类型的指针,以 bind
为例:
/*成功返回 0 ,失败返回 SOCKET_ERROR*/
int bind(SOCKET s,const struct sockaddr *name,int namelen);
结构体 struct sockaddr
用于保存地址信息中需要包含的 地址族
、端口号
、IP地址
等。该结构体的声明为:
struct sockaddr
u_short sa_family; // 地址族
char sa_data[14]; // 地址信息(端口号、IP 地址等)
;
sockaddr
用于所有协议族的地址信息,因而它的地址信息预留了 14 字节内存。
可以看到,将端口号、IP 地址这些信息写入 sa_data
数组中十分麻烦,因为端口号是 16 位数据, IP 地址是 32 位数据,需要将它们转换成字节流。为此,对于 IPv4 协议族,就有了新的结构体 sockaddr_in
:
struct sockaddr_in
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
;
有了这个结构体,IPv4 应用可以方便的填写端口号和 IP 地址信息。由于 IPv4 的地址信息只有端口号和 IP 地址,所以预留了 8 字节的 sin_zero
数组,IPv4 协议族并不使用,只是为了保持和结构体 sockaddr
的一致。
让我们看一下结构体 sockaddr_in
的成员:
sin_family
:地址族,有 IPv4 使用的地址族(AF_INET
)、IPv6 使用的地址族(AF_INET6
)sin_port
:端口号,以网络字节序保存(大端模式)sin_addr
:IP 地址,以网络字节序保存
以 bind
函数为例,看一下结构体 sockaddr_in
的使用:
struct sockaddr_in serv_addr;
// ...
if(bind(hServSock, (sockaddr*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
ErrorHandler("bind socket error");
// ...
网络字节序与地址变换
网络字节序使用大端模式。
字节序转换
unsigned short htons(unsigned short);
unsigned short ntohs(unsigned short);
unsigned long htonl(unsigned long);
unsigned long ntohl(unsigned long);
其中,h
表示 主机
(host)字节序,n
表示 网络
(network)字节序。
另外,s
表示 short
,l
表示 long
。
除了向 sockaddr_in
结构体变量填充数据需要考虑字节序外,其他情况无需考虑字节序问题。
网络地址的初始化与分配
sockaddr_in
中保存地址信息的成员为32位整数,下面给出 点分十进制
表示法与 32 位整形 IP 转换函数:
in_addr_t inet_addr(const char *string);
char *inet_ntoa(struct in_addr adr); //不可重入
网络地址初始化一般方法:
struct sockaddr_in addr;
char *serv_ip = "172.18.1.2";
char *serv_port = "4001";
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(serv_ip);
// addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(atoi(serv_port));
以上是关于socket编程在windows和linux下的区别是啥?的主要内容,如果未能解决你的问题,请参考以下文章