qt socket 传递结构体 结构体中有list_计算机网络应用--Socket编程实验(二)
本节关于socket部分函数库列表,具体基于socket的实例实现代码见下节。给出基于winSocket的简单websever实例。
2.1 WSAStartup()
【函数原型】
int WSAStartup (WORD wVersionRequested, LPWSADATA lpWSAData );
【参数】
wVersionRequested
[in] 表示欲使用的Windows Sockets API版本;这是个WORD类型的整数,高字节定义的是次版本号,低字节定义的是主版本号。lpWSAData
[in] 指向WSAData资料的指针。WSAData是结构数据类型,描述了关于Windows Sockecs底层实现的相关信息。
【返回值】
函数执行成功返回0,失败则返回如下错误代码:WSASYSNOTREADY: 底层网络子系统没有准备好。WSAVERNOTSUPPORTED:Winsock版本信息号不支持。WSAEINPROGRESS: 阻塞式Winsock1.1存在于进程中。WSAEPROCLIM: 已经达到Winsock使用量的上限。WSAEFAULT: lpWSAData不是一个有效的指针。
【函数功能】
这个函数是应用程序应该第一个调用的Winsock API函数,以完成一系列初始化的工作。
【相关数据结构】
WSADATA的定义如下:
typedef struct WSAData {WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
} WSADATA, FAR * LPWSADATA;
其中,各结构成员的含义为:
wVersion
应用程序应该使用的Winsock版本号。wHighVersion
DLL所支持的最高版本号。通常应该等于wVersion。szDescription
以0结尾的ASCII字符串,关于Winsock底层实现的描述信息。szSystemStatus
以0结尾的ASCII字符串,关于Winsock底层状态或者配置信息。iMaxSockets
一个进程最多可使用的套接字数,仅用于Winsock1.1,Winsock 2.0应该忽略该成员。iMaxUdpDg
最大的UDP报文大小,仅用于Winsock1.1,Winsock 2.0应该忽略该成员。对于Winsock 2.0,应该使用getsockopt函数取得SO_MAX_MSG_SIZE。lpVendorInfo
Winsock开发厂商信息,,仅用于Winsock1.1,Winsock 2.0应该忽略该成员。对于Winsock 2.0,应该使用getsockopt函数取得PVD_CONFIG。
【示例代码】
#include <winsock.h>
//对于Winsock 2, include <winsock2.h>WSADATA wsaData;
int nRc = WSAStartup(0x0101, & wsaData);
if(nRc)
{//Winsock初始化错误
return;
}
if(wsaData.wVersion != 0x0101)
{//版本支持不够
//报告错误给用户,清除Winsock,返回
WSACleanup();
return;
}
2.2 socket()
【函数原型】
SOCKET socket(int af, int type, int protocol);
【参数】
af
[in] 指定地址族(address family),一般填AF_INET(使用Internet地址)。type
[in] 指定SOCKET的类型:SOCK_STREAM(流类型),SOCK_DGRAM(数据报类型)。protocol
[in] 指定af参数指定的地址族所使用的具体一个协议。建议设为0,那么它就会根据地址格式和SOCKET类型,自动为你选择一个合适的协议。另外2个常用的值为:IPPROTO_UDP和IPPROTO_TCP。
【返回值】
函数执行成功返回一个新的SOCKET,失败则返回INVALID_SOCKET。这时可以调用WSAGetLastError函数取得具体的错误代码。
【函数功能】
所有的通信在建立之前都要创建一个SOCKET。
【示例代码】
//创建数据报socket
SCOKET udpSock = socket(AF_INET,
SOCK_DGRAM, IPPROTO_UDP);
//创建流socket
SCOKET tcpSock = socket(AF_INET,
SOCK_STREAM, IPPROTO_TCP);
2.3 bind()
【函数原型】
int bind(SOCKET s, const struct sockaddr FAR* name, int namelen);
【参数】
s
[in] 一个需要绑定的SOCKET,例如用socket函数创建的SOCKET。name
[in] 指向描述通信对象地址信息的结构体sockaddr的指针。在该结构体中可以指定地址族(一般为 AF_INET)、主机的地址和端口。通常把主机地址指定为INADDR_ANY(一个主机可能有多个网卡)。namelen
[in] name指针指向的结构体的长度。
【返回值】
函数执行成功返回0,失败则返回SOCKET_ERROR。这时可以调用WSAGetLastError函数取得具体的错误代码。
【函数功能】
成功地创建了一个SOCKET后,用bind函数将SOCKET和主机地址绑定。
【相关数据结构】
struct sockaddr {u_short sa_family;
char sa_data[14];
};
sa_family
地址族,比如AF_INET,2个字节大小。sa_data
用来存放地址和端口,14个字节大小。
sockaddr结构是一个通用的结构(因为Winsock支持的协议族不只是TCP/IP)。对TCP/IP协议,用如下结构来定义地址和端口。
struct sockaddr_in {short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
sin_family
地址族,设为AF_INET。sin_port
端口号。如果端口号为0,Winsock会自动为应用程序分配一个值在1024-5000间的一个端口号,所以客户端一般把sin_port设为0。sin_addr
为in_addr结构类型,用来指定IP地址。通常把主机地址指定为INADDR_ANY(一个主机可能有多个网卡)。结构in_addr下面介绍。sin_zero
8字节的数组,值全为0。这个8个字节用来填充结构sockaddr_in,使其大小等于结构sockaddr(16字节)。
结构in_addr用来指定IP地址,其定义为:
struct in_addr {union {struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;struct { u_short s_w1,s_w2; } S_un_w;u_long S_addr;} S_un;
};
对于IP地址10.14.25.90,sockaddr_in结构中的sin_addr可以这样赋值:
sin_addr. S_un .S_un_b. s_b1 = 10;
sin_addr. S_un .S_un_b. s_b2 = 14;
sin_addr. S_un .S_un_b. s_b3 = 25;
sin_addr. S_un .S_un_b. s_b4 = 90;
或者
sin_addr. S_un . S_un_w. s_w1 = (14<<8)|10;
sin_addr. S_un . S_un_w. s_w2 = (90<<8)|25;
或者
sin_addr. S_un . S_addr = (90<<24)|(25<<16)|(14<<8)|10;
或者
sin_addr. S_un . S_addr = inet_addr(“10.14.25.90”);
这里的inet_addr函数可以将字符串形式的IP地址转换为unsigned long形式的值。
【示例代码】
SOCKET sServSock;
sockaddr_in addr;//创建socket
sServSock = socket(AF_INET, SOCK_STREAM, 0);addr.sin_family = AF_INET;//htons和htonl函数把主机字节顺序转换为网络字节顺序,分别用于//短整型和长整型数据
addr.sin_port = htons(5050);
addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // LPSOCKADDR类型转换是必须的
int nRc = bind(sServSock, (LPSOCKADDR)&addr, sizeof(addr) );
2.4 listen()
【函数原型】
int listen (SOCKET s, int backlog);
【参数】
s
[in] 一个已经绑定但未连接的SOCKET。backlog
[in] 等待连接的队列的长度,可取SOMAXCONN。如果某个客户程序要求连接的时候,服务器已经与其他客户程序连接,则后来的连接请求会放在等待队列中,等待服务器空闲时再与之连接。当等待队列达到最大长度(backlog指定的值)时,再来的连接请求都将被拒绝。
【返回值】
函数执行成功返回0,失败则返回SOCKET_ERROR。这时可以调用WSAGetLastError函数取得具体的错误代码。
【函数功能】
对于服务器的程序,当申请到SOCKET,并将通信对象指定为INADDR_ANY之后,就应该等待一个客户机的程序来要求连接,listen函数就是把一个SOCKET设置为这个状态。
2.5 accept()
【函数原型】
SOCKET accept (SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen );
【参数】
s
[in] 一个已经处于listen状态的SOCKET。addr
[out] 指向sockaddr结构体的指针,里面包含了客户端的地址和端口。addrlen
[out] int型指针,指向的内容为addr指针指向的结构体的长度。
【返回值】
如果函数执行成功,会建立并返回一个新的SOCKET来与对方通信,新建的SOCKET与原来的SOCKET(函数的第一个参数s)有相同的特性,包括端口号。原来的SOCKET继续等待其他的连接请求。而新生成的SOCKET才是与客户端通信的实际SOCKET。所以一般将参数中的SOCKET称作“监听”SOCKET,它只负责接受连接,不负责通话;而对于函数返回的SOCKET,把它称作“会话”SOCKET,它负责与客户端通话。
如果失败则返回INVALID_SOCKET。这时可以调用WSAGetLastError函数取得具体的错误代码。
【函数功能】
accept函数从等待连接的队列中取第一个连接请求,并且创建一个新的SOCKET来负责与客户端会话。
【示例代码】
SOCKET sServSock; //服务器监听socket
sockaddr_in addr;
int nSockErr;
int nNumConns = 0; //当前请求连接数
SOCKET sConns[5]; //会话SOCKET数组
sockaddr ConnAddrs[5];//请求连接的客户端地址
int nAddrLen;//创建服务器监听socket
sServSock = socket(AF_INET, SOCK_STREAM, 0);addr.sin_family = AF_INET;
addr.sin_port = htons(5050);
addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);if( bind(sServSock,(LPSOCKADDR)&addr,sizeof(addr)) ==
SOCKET_ERROR )
{nSockErr = WSAGetLastError();
//绑定出错处理
}
//监听客户端请求连接
if( listen(sServSock, 2) == SOCKET_ERROR)
{nSockErr = WSAGetLastError();
//出错处理
}while( nNumConns < 5){//每当收到客户端连接请求,创建新的会话SOCKET,保存在/ //sConns数组中
//客户端地址保存在ConnAddrs数组中
sConns[nNumConns] = accept(sServSock,
ConnAddrs[nNumConns], &nAddrLen);
if(sConns[nNumConns] == INVALID_SOCKET)
{nSockErr = WSAGetLastError();
//创建会话SOCKET出错处理
}
else
{//创建会话SOCKET成功,启动新的线程与客户端会话
StartNewHandlerThread(sConns[nNumConns]);
//当前请求连接数+1
nNumConns ++;
}
}
2.6 connect()
【函数原型】
int connect (SOCKET s, const struct sockaddr FAR* name,int namelen );
【参数】
s
[in] 一个未连接SOCKET,一般是由socket函数建立的。name
[in] 同bind函数。namelen
[in] 同bind函数。
【返回值】
函数执行成功返回0,失败则返回SOCKET_ERROR。这时可以调用WSAGetLastError函数取得具体的错误代码。
【函数功能】
向对方主动提出连接请求。
2.7 send()
【函数原型】
int send (SOCKET s, char * buf, int len ,int flags);
【参数】
s
[in] 一个已经连接的SOCKET。buf
[in] 指向要传输的数据的缓冲区的指针。len
[in] buf的长度。flags
[in]指定函数调用的方式。一般取0。
【返回值】
函数执行成功返回发送的字节数(可能小于len),失败则返回SOCKET_ERROR。这时可以调用WSAGetLastError函数取得具体的错误代码。
【函数功能】
通过已经连接的SOCKET发送数据。
2.8 recv()
【函数原型】
int recv (SOCKET s, char * buf, int len ,int flags);
【参数】
s
[in] 一个已经连接的SOCKET。buf
[out] 指向接收数据的缓冲区的指针。len
[in] buf的长度。flags
[in]指定函数调用的方式。一般取0。
【返回值】
函数执行成功返回接收到数据的字节数。如果失败则返回SOCKET_ERROR。这时可以调用WSAGetLastError函数取得具体的错误代码。
【函数功能】
通过已经连接的SOCKET接收数据。当读到的数据字节少于规定接受的数目(len)时,就把数据全部接收,并返回实际接收到的字节数;当读到的数据多于规定的值时,在流方式下剩余的数据由下个recv读出,在数据报方式下多余的数据被丢弃。
2.9 sendto()
【函数原型】
int sendto (SOCKET s, char * buf, int len ,int flags, struct sockaddr_in * to, int tolen);
【参数】
s
[in] 一个SOCKET(可能已连接)。buf
[in] 指向要传输的数据的缓冲区的指针。len
[in] buf的长度。flags
[in] 指定函数调用的方式。一般取0。to
[in] 指向目标地址结构体的指针。tolen
[in] 目标地址结构体的长度。
【返回值】
函数执行成功返回发送的字节数(可能小于len),失败则返回SOCKET_ERROR。这时可以调用WSAGetLastError函数取得具体的错误代码。
【函数功能】
该函数一般用于通过无连接的SOCKET发送数据报文,报文的接受者由to参数指定。
2.10 recvfrom()
【函数原型】
int recvfrom (SOCKET s, char * buf, int len ,int flags, struct sockaddr_in * from, int * fromlen);
【参数】
s
[in] 一个已经绑定的SOCKET。buf
[out] 指向接收数据的缓冲区的指针。len
[in] buf的长度。flags
[in] 指定函数调用的方式。一般取0。from
[out] 指向源地址结构体的指针。fromlen
[in/out] 源地址结构体的长度。
【返回值】
函数执行成功返回发送的字节数(可能小于len),失败则返回SOCKET_ERROR。这时可以调用WSAGetLastError函数取得具体的错误代码。
【函数功能】
该函数一般用于通过无连接的SOCKET接收数据报文,报文的发送者由from参数指定。
2.11 closesocket()
【函数原型】
int closesocket (SOCKET s,);
【参数】
s
[in] 要关闭的SOCKET。
【返回值】
函数执行成功返回0,失败则返回SOCKET_ERROR。这时可以调用WSAGetLastError函数取得具体的错误代码。
【函数功能】
关闭指定的SOCKET。
qt socket 传递结构体 结构体中有list_计算机网络应用--Socket编程实验(二)相关推荐
- 三、初识Socket套接字结构体
一.初识Socket套接字结构体 1.通用套接字结构体类型 struct sockaddr{sa_family_t sa_family; //协议簇char sa_data[14]; //协议簇数据} ...
- python中的记录指针_使用Python向C语言的链接库传递数组、结构体、指针类型的数据...
使用python向C语言的链接库传递数组.结构体.指针类型的数据 由于最近的项目频繁使用python调用同事的C语言代码,在调用过程中踩了很多坑,一点一点写出来供大家参考,我们仍然是使用ctypes来 ...
- python结构体数组传出接收c动态库_使用Python向C语言的链接库传递数组、结构体、指针类型的数据...
使用python向C语言的链接库传递数组.结构体.指针类型的数据 由于最近的项目频繁使用python调用同事的C语言代码,在调用过程中踩了很多坑,一点一点写出来供大家参考,我们仍然是使用ctypes来 ...
- 如何通过结构化智能体完成物理构造任务?| 技术头条
作者 | Victor Bapst, Alvaro Sanchez-Gonzalez,Carl Doersch, Kimberly L. Stachenfel 译者 | Linstancy 编辑 | ...
- c语言结构体共用体枚举实例程序,10-C语言结构体-共用体-枚举
结构体是什么? 结构体和数组一样属于构造类型 数组是用于保存一组相同类型数据的,而结构体是用于保存一组不同类型的数组 定义结构体 在使用结构体之前必须先定义结构体类型,因为C语言不知道你的结构体中需要 ...
- C++ 基础入门 之 结构体/结构体定义和使用/结构体数组/结构体指针/ 结构体嵌套结构体/结构体做函数参数/结构体中 const 使用场景/结构体案例
C++ 基础入门 之 结构体/结构体定义和使用/结构体数组/结构体指针/ 结构体嵌套结构体/结构体做函数参数/结构体中 const 使用场景/结构体案例 目录 一.简单介绍 二.结构体定义和使用 三. ...
- 【结构体】 结构体引用、结构体数组指针、包含结构的结构体
目录 一.概念.变量的定义 初识结构体 结构体变量的定义.引用结构体类型的初始化 二.结构体的数组 认识结构体数组 初始化结构体数组 三.结构体指针 初识结构体指针 指向结构体数组的指针 结构体作为函 ...
- 2020.1.13 C语言学习 结构体+结构体数组+结构体指针
结构体 结构体的形式 struct 结构体名称 { 结构体成员1; 结构体成员2; - }; 例如: 图书的结构体 struct Book {char title[128];char author[4 ...
- C++结构体 结构体定义和使用、结构体数组、结构体指针、结构体嵌套结构体、结构体做函数参数
C++结构体 第二章 C++结构体 1.结构体定义和使用 语法:struct 结构体名 { 结构体成员列表 }: 通过结构体创建变量的方式有三种: struct 结构体名 变量名 struct 结构体 ...
最新文章
- python内置库之学习ctypes库(三)--调用Win32API
- 如何修改可运行Jar包,如何反编译Jar包
- Spring JDBC-事务方法嵌套调用解读
- BlockingQueue常用方法add、off、put、take、poll使用说明
- 如何在pycharm添加扩张工具
- 敏捷冲刺每日报告——Day5
- 前端:常用的meta标签总结
- ASP.NET Core on K8S学习初探(3)部署API到K8S
- mysql占用内存吗_mysql占多少内存
- Gartner:阿里云蝉联全球第三、亚太第一
- jquery validate 联动验证
- 分享Silverlight/WPF/Windows Phone/HTML5一周学习导读(2月13日-2月19日)
- ps软件打不开计算机受限制,win10系统打不开ps软件的处理技巧
- vue @cliick.stop @click.prevent @click.self
- if语句与switch语句
- 联想服务器怎么做系统备份,联想笔记本怎么做系统备份
- 【调剂】211北京科技大学钢铁共性技术协同创新中心2020年硕士研究生招生拟接收调剂公告...
- Linux命令:Nginx的启动、停止与重启
- JS设置select标签选中的值
- Mongodb 3.6安装过程(centos7.9)
热门文章
- 使用C语言将一个数组首尾互换后输出,函数实现体会地址传递
- 测验8.2 指针与字符串 6-1 函数实现字符串逆序
- sys接口linux编程,网络编程常用接口的内核实现----sys_listen()
- c语言中switch语句流程图_C语言:C语言保留字(关键字)
- 小程序如何选择云服务器,小程序怎么选择云服务器配置
- java 重复提交_java解决重复提交表单
- Java黑皮书课后题第2章:2.18(打印表格)编写程序,显示下面的表格,将浮点数值类型转化为整数
- android动态获取输入值,Android实现动态自动匹配输入内容
- 2006---2009年杭电计算机历年研究生复试---笔试编程
- 【easy】206. Reverse Linked List 链表反转