套接字编程(一)

Windows下与Linux下套接字结构体区别

套接字地址结构

大多数套接字函数都需要一个指向套接字地址结构的指针作为参数。每个协议族都定义它自己的套接字地址结构,以sockaddr_开头,并以对应每个协议族的唯一后缀结尾

IPv4套接字地址结构

IPv4套接字地址结构通常也称为“网际套接字地址结构”,它以sockaddr_in命名
在unix下:定义在<netinet/in.h>头文件中
在Windows下:定义在<winsock.h>头文件中

 //UNIX下:
 typedef unsigned int in_addr_t;//至少是32位无符号整数类型 
 typedef unsigned short int in_port_t;//至少是16位无符号整数类型
 typedef unsigned short int sa_family_t;//可以是任何无符号整数类型 
 struct in_addr {  
 	in_addr_t s_addr;//32位的IPv4地址网络字节排序 
 }; 
 struct sockaddr_in { 
 	sa_family_t sin_family;//协议族  
 	in_port_t sin_port;//16位TCP或UDP端口号,网络字节排序  
 	struct in_addr sin_addr;  
	char sin_zero[8];//不使用
 };
//Windows下
using u_short = unsigned short;

//该地址用于划分A,B,C类地址时期所用
typedef struct in_addr 
{  
	union  {  
		//访问IPv4地址的所有4个字节  
		 struct {    
			UCHAR s_b1, s_b2, s_b3, s_b4;   
		}S_un_b;  
		 //访问IPv4地址的2个16位值   
		struct   {    
			USHORT s_w1, s_w2;   
		}S_un_w;  
		 //格式化为u_long的IPv4地址  
		 ULONG S_addr; 
	 } S_un;
#define s_addr  S_un.S_addr // 可以用于大多数tcp和ip代码
#define s_host  S_un.S_un_b.s_b2    // host on imp
#define s_net   S_un.S_un_b.s_b1    // network
#define s_imp   S_un.S_un_w.s_w2    // imp
#define s_impno S_un.S_un_b.s_b4    // imp #
#define s_lh    S_un.S_un_b.s_b3    // logical host 
} IN_ADDR, * PIN_ADDR, FAR* LPIN_ADDR;

struct sockaddr_in { 
	 short   sin_family;  
	 u_short sin_port;  
	 struct  in_addr sin_addr;  
	 char    sin_zero[8];//未使用,通常设为0;
}; 

32位IPv4地址存在两种不同的访问方法。如果使用sin_addr将按in_addr结构引用其中的32位IPv4地址,而sin_addr.s_addr将按in_addr_t(无符号32位整数)引用同一个32位IPv4地址
Windows下与Unix下并无任何区别,在不同主机之间的通信中,这个结构不在主机之间传递

通用套接字接口

在作为一个参数传递进任何套接字函数时,套接字地址总是以指针的形式来传递,但是必须先强制转换成通用套接字结构(支持所有协议族的套接字地址结构)

//Unix下:bits/socket.h 
using sa_family_t = unsigned short int; 
struct sockaddr {  
	sa_family_t  sa_family;//协议族  
	char sa_data[14];//地址数据 
};
using u_short = unsigned short; 

//Windows下 
struct sockaddr { 	
	u_short sa_family;  //协议族 	
	char    sa_data[14];//地址数据 
}//套接字函数原型 
int bind(int, const struct sockaddr*, int); 

所以,在使用套接字函数的时候,需要将指向特定协议的套接字结构强制转换成通用套接字,而通用套接字在这两个环境下并无区别

IPv6套接字地址结构
//Unix下:bits/socket.h
struct in6_addr
{
	unsigned char u6_addr[16];//128位IPv6地址
};
struct sockaddr_in6
{
	unsigned short int sin6_famliy;//AF_INET6
	unsigned short int sin6_port; // 端口号
	unsigned int sin6_flowinfo; //IPv6流信息
	struct in6_addr sin6_addr; /* IPv6 地址 */
	unsigned int sin6_scope_id; //IPv6范围标识
};
//Windows下<ws2ipdef.h>
typedef struct in6_addr
{
	union
	{//128位IPv6地址
		unsigned char Byte[16];
		unsigned short Word[8];
	} u;
};

typedef struct sockaddr_in6
{
	unsigned short sin6_family; // AF_INET6.
	unsigned short sin6_port;   //端口号
	unsigned long  sin6_flowinfo; // IPv6流信息。
	in6_addr sin6_addr;         // IPv6 地址.
	union
	{
		unsigned long sin6_scope_id; // IPv6范围标识
		SCOPE_ID sin6_scope_struct;
	};
} SOCKADDR_IN6_LH;

IPv6的地址族是AF_INET6,而IPv4的地址族是AF_INET
结构中字段的先后顺序做过编排,使得该结构本身是64位对齐的
sin6_flowinfo字段分成两个字段:
- 低序20位是流标
- 高序12位保留
sin6_scope_id字段对于具备范围的地址标识其范围;

socket套接字在Windows与Linux之间并无太大差异,只是所在头文件以及套接字结构体成员的数据类型有点区别
而在Windows下,创建一个套接字需要先加载socket库

#include <windows.h>
#include <winsock.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main
{
	WSADATA wsd;
	int Ret = 0;
 	//通知程序,加载socket库
 	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
 	{
  	cout << "socket初始化失败: " << WSAGetLastError() << endl;
  	return -1;
 	}
 	/*创建套接字。。。。
 	*
 	*
 	*/

 	//通过WSACleanup()关闭该动态库
 	WSACleanup();//关闭socket库
 	return 0;
 }

在Linux下只需要直接创建套接字即可:

#include <netinet/in.h>
int main(int argc, char **argv)
{
	sockaddr_in servaddr;
	/* 创建套接字
	*
	*
	*/
	return 0}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值