SOCKET基础学习笔记

    技术2022-05-11  85

     PS:为了区分SOCKET函数版本,Winsock2版本前加WSA前缀,例如:socket WSASocket;对采用Winsock 1的应用而言,必须有Wi n s o c k . h包容文件,而对使用Winsock 2的应用而言,则需要Winsock 2.h包容文件。 int WSAGetLastError(void);发生错误之后调用这个函数,就会返回所发生的特定错误的完整代码。 一旦为某种特定协议创建了套接字,就必须将套接字绑定到一个已知地址。 int bind( SOCKET s; //希望在上面等待客户机联机的套接字 const struct sockaddr FAR* name; //地址缓冲区 int namelen; ); SOCKET s; struct sockaddr_in tcpaddr; int port=5150; s=socket(AF_INET,SOCK_STRAM,IPPROTO_TCP); tcpaddr.sin_family=AF_INET; tcpaddr.sin_port=htons(port); tcpaddr.sin_addr.s_addr=htonl(INADDR_ADY); bind(s,(SOCKADDR*)&tcpaddr,sizeof(tcpaddr)); b i n d函数的作用只是将一个套接字和一个指定的地址关联在一起。指示一个套接字等候进入连接的A P I函数则是l i s t e n int listen( SOCKET s, int backlog //等待连接的最大个数 ); 当我们都做好准备时,就可以用accept函数来接受连接 SOCKET accepy( SOCKET s, struct sockaddr FAR* addr,//发出连接请求的套接字信息 int FAR* addrlen //第二个参数的长度 ); a c c e p t会返回一个新的套接字描述符,它对应于已经接受的那个客户机连接。对于该客户机后续的所有操作,都应使用这个新套接字。至于原来那个监听套接字,它仍然用于接受其他客户机连接,而且仍处于监听模式。 SOCKET WSAAccept( SOCKET s, struct sockaddr FAR* addr, LPINT addrlen, LPCONDITIONPROC lpfnCondition, //回调函数定义如下 DWORD dwCallbackData //????? ); int CALLBACK ConditionFunc( LPWSABUF lpCallerId, //连接实体的地址 LPWSABUF lpCallerData, //连接实体附带的请求数据(一般不支持) LPQOS lpSQOS, //独立连接时需要的带宽 LPQOS lpGQOS, //套接字组连接需要的带宽(不支持) LPWSABUF lpCalleeId, //客户机连接的本地地址 LPWSABUF lpCalleeData, //可以作为连接请求的一部分返回给客户机(一般不支持) GROUP FAR* g,//??????? DWORD dwCallbackData //????????? ); typedef struct _WSABUF{ u_long len; char FAR* buf; }WSABUF,FAR* LPWSABUF; connect函数和WSAConnect函数 int connect( SOCKET s, const struct sockaddr FAR* name, int namelen ); int WSAConnect( SOCKET s, const struct sockaddr FAR* name, int namelen, LPWSABUF lpCallerData, //发送给服务器的附加数据 LPWSABUF lpCalleeData,//服务器传回的附加数据(不支持) LPQOS lpSQOS, //套接字需要的网络质量 LPQOS lpGQOS ); 数据收发没有Unicode版本,所以经常用到WideCharToMultiByte把UNICODE转换为ASCII版本 int send( SOCKET s, const char FAR* buf, int len, int flags ); l a g s可为0、M S G _ D O N T R O U T E或M S G _ O O B。另外, f l a g s还可以是对那些标志进行按位“或运算”的一个结果。M S G _ D O N T R O U T E标志要求传送层不要将它发出的包路由出去。 M S G _ O O B标志预示数据应该被带外发送(紧急数据) int WSASend( SOCKET s, LPWSABUF lpBuffers, //发送的一组结构多用于分散集合I/O DWORD dwBufferCount, //传送的结构数 LPDWORD lpNumberOfBytesSent, //字节总发送数 DWORD dwFlags, LPWSAOVERLAPPED lpOverlapped, //用于重叠I/O LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE //用于重叠I/O ); int recv( SOCKET s, char FAR* buf, int len, int flags ); f l a g s参数可以是下面的值: 0、M S G _ P E E K或M S G _ O O BM S G _ P E E K会使有用的数据复制到所提供的接收端缓冲内,但是没有从系统缓冲中将它删除 int WSARecv( SOCKET s, LPWSABUF lpBuffers, DWORD deBufferCount, LPDWORD lpNumberOfBytesReceived, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE ); M S G _ PA RT I A L标志使用和出现的地方不同,其含义也不同。对面向消息的协议来说,这个标志是W S A R e c v调用返回后设置的(如果因为缓冲空间不够导致整条消息未能在这次调用中返回的话)。这时,后面的W S A R e c v调用就会设置这个标志M A S G _ PA RT I A L,直到整条消息返回,才把这个标志清除。如果这个标志当作一个输入参数投递,接收操作应该在一收到数据就结束,即使它收到的只是整条消息中的一部分。 int shutdown( SOCKET s, int how ); //用于从容关闭端口 h o w参数可以是下面的任何一个值: S D _ R E C E I V E、S D _ S E N D或S D _ B O T H。如果是 S D _ R E C E I V E,就表示不允许再调用接收函数。这对底部的协议层没有影响。另外,对T C P套接字来说,不管数据在等候接收,还是数据接连到达,都要重设连接。尽管如此, U D P套接字上,仍然接受并排列接入的数据。如果选择S E _ S E N D,表示不允许再调用发送函数。对T C P套接字来说,这样会在所有数据发出,并得到接收端确认之后,生成一个F I N包。最后,如果指定S D _ B O T H,则表示取消连接两端的收发操作。 无连接协议下 int recvfrom( SOCKET s, char FAR* buf, int len, int flags, //M S G _ O O B和M S G _ P E E K struct sockaddr FAR* from, int FAR* fromlen ); int WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesReceivd, LPDWORD lpFlags, //0、M S G _ O O B、M S G _ P E E K或M S G _ PA RT I A L struct sockaddr FAR* lpFrom, LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPELTION_ROUTINE lpCompletionROUTINE ); int sendto( SOCKET s, const char FAR* buf, int len, int flags, const struct sockaddr FAR* to, //服务器目标地址 int tolen ): int WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, DWORD dwBufferCount, LPDWROD lpNumberOfBytesSent, DWORD dwFlags, const struct sockaddr FAR* lpTo, int iTolen, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_CONPLETION_ROUTINE lpCompletionROUTINE ); 其他函数 获得通信方的套接字地址信息,该信息是关于已建立连接的那个套接字的 int getpeername(                         SOCKET s, struct sockaddr FAR* name, int FAR* namelen ); 指定套接字的本地接口的地址信息 getsockname( SOCKET s, struct sockaddr FAR* name, int FAR* namelen ); Tr a n s m i t F i l e Tr a n s m i t F i l e是微软专有的Wi n s o c k扩展,它允许从一个文件中传输高性能数据。这是非常有效的,因为整个数据传输可在内核模式中进行。也就是说,如果你的应用从指定的文件中读取一堆数据,然后用s e n d或W S A S e n d时,涉及到“用户模式到内核模式传输”的发送调用就有若干个。有了Tr a n s m i t F i l e,整个读取和发送数据的进程就可在内核模式中进行。该函数的定义如下: BOOL TransmitFile( SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, //要发送的文件大小,0为全部 DWORD nNumberOfBytesPerSend, //以多大的数据块进行发送,0为默认 LPOVERLAPPED lpOverlapped, LPTRASMIT_FILE_BUFFERS lpTrasmitBuffers, //文件传输之前和之后要发送的数据 DWORD dwFlags  //如下 ); typedef struct _TRANSMIT_FILE_BUFFERS{ PVOID Head; //文件发送之前要发送的数据 DWORD HeadLength; PVOID Tail; //文件发送完成之后要发送的数据 DWORD TailLength; }TRANSMIT_FILE_BUFFERS; T F _ D I S C O N N E C T 数据发送完毕之后,开始执行套接字关闭 TF_REUSE_SOCKET允许套接字句柄再次做为客户机套接字用于AcceptEx中 T F _ U S E _ D E FA U LT _ W O R K E R 表明传输应该在系统默认线程场景中进。特别有利于长文件传输 T F _ U S E _ S Y S T E M _ T H R E A D 表明传输应该在系统线程场景中进行。同样有利于长文件传输 T F _ U S E _ K E R N E L _ A P C 表明“内核异步进程调用”(A P C)应该对文件传输进行处理。如果把指定文件读入缓冲区只需要一次读取,该标志便可提供一个重要的性能提升 T F _ W R I T E _ B E H I N D 表明Tr a n s m i t F i l e应该在无须远程系统对所有的数据进行收到确认的情况下结束  

    最新回复(0)