欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WindowsSocket编程(tcp篇)

程序员文章站 2022-04-08 21:38:46
...

一、头文件和库
1、导入头文件winsock2.h
2、链接ws2_32.lib
链接库步骤:快捷键Alt + F7 --> 配置属性 --> 输入 --> 附加依赖项快捷键Alt + F7 --> 配置属性 --> 输入 --> 附加依赖项

二、Winsock初始化

#include <winsock2.h>
/*进行Winsock编程时,必须首先调用WSAStartup函数,设置程序中用到的Winsock版本,并初始化相应版本的库*/
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSADATA);

参数1:Winsock版本:可使用宏MAKEWORD(1,2);该宏返回字节类型数据0x0201;
参数2:WSADATA结构体的指针类型。
返回值:成功时返回0,失败时返回非0的错误代码。

#include <winsock2.h>
/*程序结束之前调用此函数*/
int WSACleanup(void);	//成功时返回0,失败时返回SOCKET_ERROR

例子

WSADATA wsaData;
int WSAStartup( MAKEWORD(1,2), &wsaData );
WSACleanup();

三、Windows套接字相关函数

SOCEKT socket( int af, int type, int protocol );

参数1:协议族。可选参数为(PF_INET, PF_INET6, PF_LOCAL, PF_PACKET, PF_IPX);有些地方也将PF写作AF,两者是相同的。
参数2:套接字类型。可选参数(SOCK_STREAM, SOCK_DGRAM);
参数3:协议的最终选择。大部分情况可以直接传递参数0,可选参数(IPPROTO_TCP, IPPROTO_UDP);
返回值:成功时返回套接字句柄,失败时返回INVALID_SOCKET;

int bind( SOCKET s, const struct sockadd * name, int namelen );

参数1:要分配地址信息(IP地址和端口号)的SOCKET句柄
参数2:存有地址信息的结构体变量
参数3:第二个结构体变量的长度
返回值:成功时返回0,失败时返回SOCKET_ERROR;

int listen( SOCKET s, int backlog );

参数1:希望进入连接等待的套接字句柄,传递的套接字句柄成为服务器端套接字(监听套接字)
参数2:连接请求队列的长度,若为5,则最多使5个连接请求进入队列
返回值:成功时返回0,失败时返回SOCKET_ERROR;

int accpt( SOCKET s, const struct sockadd * addr, int * addrlen );

参数1:服务器端套接字句柄
参数2:保存发起请求的客户端地址信息,传入参数为sockaddr_in结构体,需使用(sockaddr*)强转
参数3:第二个参数sockadd结构体的长度
返回值:成功时返回0,失败时返回SOCKET_ERROR;

int connect( SOCKET s, const struct sockadd * name, int namelen );

参数1:客户端套接字句柄
参数2:保存目标服务器的信息,传入参数为sockaddr_in结构体,需使用(sockaddr*)强转
参数3:第二个参数值的长度
返回值:成功时返回0,失败时返回SOCKET_ERROR;

int closesocket( SOCKET s );

参数1:要关闭的套接字句柄
返回值:成功时返回0,失败时返回SOCKET_ERROR;

四、Windows的I/O函数

int send( SOCKET s, const char * buf, int len, int flags );

参数1:表示数据传输对象连接的套接字句柄值
参数2:保存待传输数据的缓冲地址值
参数3:要传输的字节数
参数4:要传输信息时用到的多种选项信息
返回值:成功时返回传输字节数,失败时返回SOCKET_ERROR;

int recv( SOCKET s, const char * buf, int len, int flags );

参数1:表示数据接收对象连接的套接字句柄值
参数2:保存接收数据的缓冲地址值
参数3:能够接收的最大字节数
参数4:接收数据时用到的多种选项信息
返回值:成功时返回接收的字节数(收到EOF时为0),失败时返回SOCKET_ERROR;

五、结构体

struct sockaddr_in{
	sa_family_t  sin_family; 	//地址族。可选参数为(AF_INET, AF_INET6, AF_LOCAL);
	uint16_t sin_port;		//16位端口号,以网络字节序保存
	struct in_arrd  sin_addr;	//32位的IP地址信息,以网络字节序保存。使用inet_addr(INADDR_ANY)可直接获取本机IP
	char  sin_zero[8];	//无特殊含义,必须填充位0
}

struct in_addr{
	Inaddr_t  s_addr;
}

六、字节序
大端序(网络字节序):高字节存放在低位地址
小端序:高字节存放在高位地址

字节序转换:
unsigned short htons(unsigned short);
unsigned short ntohs(unsigned short);
unsigned long htonl(unsigned long);
unsigned long ntohl(unsigned long);
htons中的h代表主机(host)字节序;
htons中的n代表主机(network)字节序。
  另外,以s作为后缀的函数中,s表示两个字节的short,用于端口号转换。以l作为后缀的函数中,l表示4个字节的long,用于IP地址转换。

七、网络地址的初始化与分配
1、将字符串信息转化为网络字节序

in_addr_t inet_addr(const char* string);	//参数为ip地址。成功时返回32位大端序整数值,失败时返回INADDR_NONE

2、将网络字节序整型转化为字符串ip地址

char* inet_ntoa(struct in_addr addr);	//成功时返回字符串ip值,失败返回-1

八、域名及IP的转换
1、通过域名获得IP

/*	传入字符串域名,返回IP地址。成功时返回struct地址,失败时返回NULL	*/
#include <winsock2.h>
struct hostent * gethostbyname(const char * name);

2、通过IP获得域名

/*	传入IP,获得对应的域名信息。成功时返回struct地址,失败时返回NULL	*/
#include <winsock2.h>
struct hostent * gethostbyaddr(const char * addr, int len, int type);

参数1:含有IP地址信息的in_addr结构体指针,为了同时传递IPv4地址之外的其他信息,该变量声明为char指针
参数2:向第一个参数传递地址的字节数,IPv4时为4,IPv6时为16
参数3:传递地址族信息,IPv4时为AF_INET,IPv6时为AF_INET6

相关标签: socket编程 socket