热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

winsocket研究了一天的成果

首先,这都是套路(▼-▼)头文件#include#include用这个,这个是升级版各个函数解释1、WSA

首先,这都是套路( ▼-▼ )

 

头文件     #include

             #include 用这个,这个是升级版

各个函数解释

1、WSAStartup:

初始化套接字环境,本函数必须是应用程序或DLL调用的第一个Windows Sockets函数.它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Sockets实现的细节.应用程序或DLL只能在一次成功的WSAStartup()调用之后才能调用进一步的Windows Sockets API函数.


int WSAStartup(WORD  wVersionRequested, 
LPWSADATA  lpWSAData);

实际用例

//begin 初始化网络环境
int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
if ( err != 0)
{printf(
"WSAStartup failed with error: %d\n", err);return -1;
}
//end

2、WSACleanup:

清理套接字环境,和上面的WSAStartup相反,该函数是在程序不在对任何Windows Sockets函数调用后,用其来清理套接字环境的
int  WSACleanup (void);

 

3、SOCKET socket(int af, int type, int protocol);
建立套接字 参数af用于指定网络地址类型,一般取AF_INET,表示该套接字在Internet域中,进行通信。 参数type用于知道套接字的类型,若取SOCK_STREAM表示创建的套接字是流套接字,而取SOCK_DGRAM创建数字报套接字。参数protocol用于指定网络协议,一般取0,表示默认为TCP/IP协议。 若套接字创建成功则该函数返回创建的套接字句柄SOCKET,否则产生INVALID_SOCKET错误。
实际用例

//begin socket 一个套接字
hTcpSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == hTcpSocket)
{
MJS_LOG_ERROR(
"socket failed with error: \n");
WSACleanup();
return -1 ;
}
//end

4、int listen(SOCKET s, int backlog);

将套接字置入监听模式并准备接受连接请求。其中,参数s是服务器端套接字,于指定正在等待连接的最大队列长度。如无错误发生,listen函数返回0,失败则返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。

5、SOCKET accept( SOCKET s, struct sockaddr* addr, int* addrlen );
参数s同上,addr是一个有效的SOCKADDR_IN结构的地址,而addrlen是sockaddr_in结果的长度。accept函数返回后,addr参数变量中会包含发出连接请求的那个客户机的IP地址信息,而addrlen参数则指出该结构的长度,并返回一个新的套接字描述符,它对应于已经接受的那个客户机连接。

 

6、 int bind( SOCKET s, const struct sockaddr* name, int namlen );
绑定到本地,name中指定的IP应该是当前运行该程序机器的IP。

 

7、int connect( SOCKET s, const struct sockaddr FAR* name, int namelen );
连接到服务器
实际用例

int ServePort=20000;
char ServeIP[32]="192.168.1.200";
sockaddr_in addr;
addr.sin_family
= AF_INET;
addr.sin_port
= htons(ServePort);
addr.sin_addr.S_un.S_addr
= inet_addr(ServeIP);
//连接服务器
if (connect(hTcpSocket, (sockaddr*)&addr, sizeof(sockaddr)) == -1)
{closesocket(hTcpSocket);printf(
"connect Tradesys failed with error%d,%s,%d: \n",ServePort,ServeIP,GetLastError());WSACleanup();return -1;
}
else
{printf(
"connect Tradesys sucessed,%d,%s: \n",ServePort,ServeIP);
}

若无错误发生,则connect()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。对阻塞套接口而言,若返回值为SOCKET_ERROR则应用程序调用WSAGetLsatError()。如果它指出错误代码为WSAEWOULDBLOCK,则您的应用程序可以:

1.用select(),通过检查套接口是否可写,来确定连接请求是否完成。或者,
2.如果您的应用程序使用基于消息的WSAAsynSelect()来表示对连接事件的兴趣,则当连接操作完成后,您会收到一个FD_CONNECT消息。
8、 int send( SOCKET s, const char* buf, int len, int flags );

失败时返回 -1/SOCKET_ERROR

       sockfd:已建立连接的发送端套接字描述符(非监听描述符)

       buf:应用要发送数据的缓存

       len:实际要发送的数据长度

       flags:一般设置为0。  flags可取的值有:0、MSG_DONTROUTE或MSG_OOB或这些标志的按位或运算。

 

9、int recv( SOCKET s, char* buf, int len, int flags );
s是准备接收数据的套接字,buf是即将收到数据的字符缓冲区,而len则是准备接受的字节数或buf缓冲的长度。flags一般指定为0.参数可以是0、MSG_PEEK或MSG_OOB或这些标志的按位“或”运算。

 表示从接收缓冲区拷贝数据。成功时,返回拷贝的字节数,失败返回-1。阻塞模式下,recv/recvfrom将会阻塞到缓冲区里至少有一个字节(TCP)/至少有一个完整的UDP数据报才返回,没有数据时处于休眠状态。若非阻塞,则立即返回,有数据则返回拷贝的数据大小,否则返回错误-1,置错误码为EWOULDBLOCK。

 

10、int shutdown( SOCKET s, int how );
其中,how参数用于描述禁止哪些操作,它可取的值有:SD_RECEIVE、SD_SEND或SD_BOTH。 如果是SD_RECEIVE,就表示不允许再调用接收函数, 如果选择SD_SEND,表示不允许再调用发送函数, 如果是SD_BOTH, 则表示取消连接两端的收发操作。 如果没有错误发生,shutdown()返回0,否则返回SOCKET_ERROR错误。
 
11、 int closesocket(SOCKET s );
s是要关闭的套接字描述字,再利用套接字执行调用就会失败。
12 int gethostname(char *name, size_t len):
这个函数,调用后,会将主机名保存在name里面。而len是name的大小。该函数返回0表示成功,否则失败。
13、struct hostent *gethostbyname(const char *name);
hostent结构: 

struct hostent
{
char *h_name; //*h_name 表示的是主机的规范名char **h_aliases; //h_aliases 表示的是主机的别名int h_addrtype; //地址类型AF_INET,还是AF_INET6int h_length; //IP地址占字节数char **h_addr_list; //IP地址列表
};

int   **h_addr_lisst 表示的是主机的ip地址 注意 是以网络字节序存储的。

 


14、const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) ;

这个函数,是将类型为af的网络地址结构src,转换成主机序的字符串形式,存放在长度为cnt的字符串中。这个函数,其实就是返回指向dst的一个指针。如果函数调用错误,返回值是NULL。

 

15、struct hostent FAR *PASCAL FAR gethostbyaddr(const char FAR * addr, int len, int type);
参数addr:指向网络字节顺序地址的指针。 参数len: 地址的长度,在PF_INET类型地址中为4。 参数type:指地址类型AF_INET、IF_INET6

 

16、inet_ntoa( char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
将网络地址转换成“.”点隔的字符串格式。本函数将一个用in参数所表示的Internet地址结构转换成以“.” 间隔的诸如“a.b.c.d”的字符串形式。请注意inet_ntoa()返回的字符串存放在WINDOWS套接口实现所分配的内存中。应用程序不应假设该内存是如何分配的。在同一个线程的下一个WINDOWS套接口调用前,数据将保证是有效。

参数in:一个表示Internet主机地址的结构。

返回值:若无错误发生,inet_ntoa()返回一个字符指针。否则的话,返回NVLL。其中的数据应在下一个WINDOWS套接口调用前复制出来。

 

17、unsigned long inet_addr(  const char   FAR *cp);
将点格式的IP地址转换为无符号类型存储。
18、u_short PASCAL FAR htons( u_short hostshort);
作用是将主机的无符号短整形数转换成网络字节顺序。
19、 u_short PASCAL FAR ntohs( u_short netshort);
20、u_long PASCAL FAR htonl( u_long hostlong);
本函数将一个32位数从主机字节顺序转换成网络字节顺序。
实际用例

//将主机的unsigned long值转化为网络字节顺序(32位),使用函数htonl()
//参数hostlong标识主机字节顺序的数字,函数返回一个网络字节顺序的数字
#include
#include

#pragma comment (lib,"ws2_32.lib")
void main()
{
u_long a
= 0x12345678;
u_long b
= htonl(a);
printf(
"%u/n",a);
printf(
"%x/n",a);
printf(
"%u/n",b);
printf(
"%x/n",b);
}

 

21、u_long PASCAL FAR ntohl( u_long netlong);
将一个无符号长整形数从网络字节顺序转换为主机字节顺序。
参数netlong:一个以网络字节顺序表达的32位数。
返回值:ntohl()返回一个以主机字节顺序表达的数。

//将32位网络字节转换为主机字节,使用函数ntohl()
//定义如下
u_long ntohl(u_long netlong);
#include

#include

#pragma comment(lib,"ws2_32.lib")
void
main()
{
u_long a
= 0x12345678;
u_long b
=
ntohl(a);
printf(
"%u/n",a);
printf(
"%x/n",a);
printf(
"%u/n",b);
printf(
"%x/n",b);
}

 

 

 

PS:

错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEINVAL:超时时间值非法。
WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAENOTSOCK:描述字集合中包含有非套接口的元素。
WSAEADDRINUSE:所指的地址已在使用中。
WSAEADDRNOTAVAIL:在本地机器上找不到所指的地址。
WSAENOTSUPPORT:所指族中地址无法与本套接口一起使用。
WSAECONNREFUSED:连接尝试被强制拒绝。
WSAEDESTADDREQ:需要目的地址。
WSAEFAULT:namelen参数不正确。
WSAEINVAL:套接口没有准备好与一地址捆绑。
WSAEISCONN:套接口早已连接。
WSAEMFILE:无多余文件描述字。
WSAENETUNREACH:当前无法从本主机访问网络。
WSAENOBUFS:无可用缓冲区。套接口未被连接。
WSAENOTSOCK:描述字不是一个套接口。
WSAETIMEOUT:超时时间到。
WSAEWOULDBLOCK:套接口设置为非阻塞方式且连接不能立即建立。可用select()调用对套接口写,因为select()时会进行连接。
INADDR_ANY   就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。 一般来说,在各个系统中均定义成为0值。

 

 

以下是我写的代码

server:

 

#include
#include

#include

#include

#include
<string.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib")#define PORT 8888
int main()
{
//begin 初始化网络环境
WSADATA wsaData;if(WSAStartup(MAKEWORD(2,2),&wsaData)!&#61;0){ //加载winsock2库printf("加载失败./n");return -1;}//end 初始化网络环境struct sockaddr_in servaddr; //服务器端地址memset(&servaddr, 0,sizeof(servaddr));servaddr.sin_family &#61; AF_INET; //填写要连接的服务器地址信息servaddr.sin_addr.s_addr &#61; htonl(INADDR_ANY); //inet_addr()将命令行中输入的点分IP地址转换为二进制表示的网络字节序IP地址servaddr.sin_port &#61; htons(PORT);SOCKET socks &#61; socket(AF_INET,SOCK_STREAM,0); //建立客户端流式套接口if(socks &#61;&#61; INVALID_SOCKET){printf("建立接口失败/n");return -1;}bind(socks,(struct sockaddr *)&servaddr,sizeof(servaddr)); //与服务器端建立连接listen(socks, 10); //将套接字置入监听模式并准备接受连接请求,请求10是连接队列的最大长度printf("正在连接......\n");struct sockaddr_in addrClient; int addrClient_len &#61; sizeof(addrClient); while (1) { SOCKET sockc &#61; accept(socks, (struct sockaddr *)&addrClient, &addrClient_len); //建立套接字用于通信char sen[100] &#61; {0}; sprintf(sen,"%s", inet_ntoa(addrClient.sin_addr)); // 将客户端的IP地址存入c数组中send(sockc, sen, strlen(sen) &#43; 1, 0); // 发送数据到客户端char receive[100] &#61; {0};recv(sockc, receive, 100, 0); // 接收客户端数据printf("%s\n", receive); closesocket(sockc); } closesocket(socks);system("pause");return 0;
}

client&#xff1a;

#include
#include

#include

#include

#include
<string.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
#define PORT 8888
int main()
{
//begin 初始化网络环境
WSADATA wsaData;if(WSAStartup(MAKEWORD(2,2),&wsaData)!&#61;0){ //加载winsock2库printf("加载失败/n");return -1;}//end 初始化网络环境struct sockaddr_in addrSrv;addrSrv.sin_family &#61; AF_INET; addrSrv.sin_port &#61; htons(PORT); addrSrv.sin_addr.s_addr &#61; inet_addr("10.22.26.126"); //要连接的服务器的ip地址
SOCKET sockc &#61; socket(AF_INET,SOCK_STREAM,0); //建立客户端流式套接口connect(sockc,(struct sockaddr *)&addrSrv,sizeof(addrSrv)); //与服务器进行连接char receive[250] &#61; {0};recv(sockc, receive, 250, 0); // 接收客户端数据printf("%s\n", receive); send(sockc, "hello world", strlen("hello world") &#43; 1, 0); closesocket(sockc); system("pause");return 0;
}

 分别建两个项目&#xff0c;然后打开各自的exe即可

 

 

 


转:https://www.cnblogs.com/farewell-farewell/p/5538020.html



推荐阅读
  • 使用HTML和JavaScript实现视频截图功能
    本文介绍了如何利用HTML和JavaScript实现从远程MP4、本地摄像头及本地上传的MP4文件中截取视频帧,并展示了具体的实现步骤和示例代码。 ... [详细]
  • 本文介绍了 Go 语言中的高性能、可扩展、轻量级 Web 框架 Echo。Echo 框架简单易用,仅需几行代码即可启动一个高性能 HTTP 服务。 ... [详细]
  • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
    本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • 包含phppdoerrorcode的词条 ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • 本文介绍了如何查看PHP网站及其源码的方法,包括环境搭建、本地测试、源码查看和在线查找等步骤。 ... [详细]
  • 自然语言处理(NLP)——LDA模型:对电商购物评论进行情感分析
    目录一、2020数学建模美赛C题简介需求评价内容提供数据二、解题思路三、LDA简介四、代码实现1.数据预处理1.1剔除无用信息1.1.1剔除掉不需要的列1.1.2找出无效评论并剔除 ... [详细]
  • Cookie学习小结
    Cookie学习小结 ... [详细]
  • malloc 是 C 语言中的一个标准库函数,全称为 memory allocation,即动态内存分配。它用于在程序运行时申请一块指定大小的连续内存区域,并返回该区域的起始地址。当无法预先确定内存的具体位置时,可以通过 malloc 动态分配内存。 ... [详细]
  • 本文将介绍如何在混合开发(Hybrid)应用中实现Native与HTML5的交互,包括基本概念、学习目标以及具体的实现步骤。 ... [详细]
  • 高端存储技术演进与趋势
    本文探讨了高端存储技术的发展趋势,包括松耦合架构、虚拟化、高性能、高安全性和智能化等方面。同时,分析了全闪存阵列和中端存储集群对高端存储市场的冲击,以及高端存储在不同应用场景中的发展趋势。 ... [详细]
  • 我在使用 AngularJS 的路由功能开发单页应用 (SPA),但需要支持 IE7(包括 IE8 的 IE7 兼容模式)。我希望浏览器的历史记录功能能够正常工作,即使需要使用 jQuery 插件。 ... [详细]
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • 操作系统如何通过进程控制块管理进程
    本文详细介绍了操作系统如何通过进程控制块(PCB)来管理和控制进程。PCB是操作系统感知进程存在的重要数据结构,包含了进程的标识符、状态、资源清单等关键信息。 ... [详细]
author-avatar
石蓉亮
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有