VS Socket编程

以控制台下实现为例子

准备

#include<Winsock2.h>

需要在项目中添加依赖项:Ws2_32.lib

代码

此代码实现的功能是服务器端发送数据,客户端连接上服务器端并监听服务器端发送来的数据。

客户端

#include "stdafx.h"
#include<Winsock2.h>
void _tmain(int argc, _TCHAR* argv[])
{
 //加载socket动态链接库
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 ) {
  return;
 }
if ( LOBYTE( wsaData.wVersion ) != 1 ||
   HIBYTE( wsaData.wVersion ) != 1 ) {
  WSACleanup( );
  return; 
 }
 //创建客户端套接字
    SOCKET client=socket(AF_INET,SOCK_STREAM,0);//流式套接字。(数据报套接字,原套接字)
 SOCKADDR_IN svr_addr_in;//保存服务器端的地址信息
 svr_addr_in.sin_family=AF_INET;//代表TCP/IP协议族
 //inet_addr()把字符串变成无符号的长整型。获取服务器地址.0.0.1:本机做服务器,127.0.0.1是服务器的ip地址
 svr_addr_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
 //htons本函数将一个位数从主机字节顺序转换成网络字节顺序,该端口号要与服务器的端口号相同
 svr_addr_in.sin_port=htons(6000);
 while(connect(client,(sockaddr*)&svr_addr_in,sizeof(svr_addr_in))!=0);//链接服务器,等于表示连上服务器
 char b[1024];
 for(int i=0;;i++)
 {
 recv(client,b,sizeof(b),0);//客户端接受文件
  printf("%s",b);
 }
 closesocket(client);//关闭客户端套接字
 WSACleanup();//卸载winsock动态链接库
}

服务器端

#include "stdafx.h"
#include<Winsock2.h>
void  _tmain(int argc, _TCHAR* argv[])
{
 //加载socket动态链接库
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 ) {
  return;
 }
if ( LOBYTE( wsaData.wVersion ) != 1 ||
   HIBYTE( wsaData.wVersion ) != 1 ) {
  WSACleanup( );
  return; 
 }
 SOCKET svr=socket(AF_INET,SOCK_STREAM,0);
 SOCKADDR_IN svr_addr_in;//创建一个服务器地址结构体,用于保存服务器的信息
 svr_addr_in.sin_family=AF_INET;//协议家族
 svr_addr_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//htonl(INADDR_ANY);//获取当前机子网卡ip地址
 svr_addr_in.sin_port=htons(6000);//设置端口地址
    bind(svr,(sockaddr*)&svr_addr_in,sizeof(SOCKADDR_IN));//将socket绑定到本地机地址上面
 //把服务器socket设置为监听socket,同时能监听个client客服
 listen(svr,5);
    SOCKADDR_IN client_addr_in;//用于保存客户端的信息
 int len=sizeof(SOCKADDR_IN);
    SOCKET client=accept(svr,(sockaddr*)&client_addr_in,&len);//等待(接受)客户端请求到来
 char b[1024]="ss";
 for(int i=0;;i++)
 {
 send(client,b,sizeof(b),0);//向服务器发送数据
 //system("pause"):
 }
 closesocket(client);//关闭客户端套接字
 closesocket(svr);//关闭服务器套接字
    WSACleanup();//卸载socket链接库
 return ;
}

代码解析

初始化部分

WORD wVersionRequested MAKEWORD( 1, 1 );
 WSADATA wsaData;
int err= WSAStartup( wVersionRequested, &wsaData );

MAKEWORD(a,b)是一个宏,定义如下:

#defineMAKEWORD(a,b)((WORD)(((BYTE)(((DWORD_PTR)(a))&0xff))|((WORD)((BYTE)(((DWORD_PTR)(b))&0xff)))<<8))

目的是将两个单字节拼成一个双字节,比如(1,1)会被拼成0x0101.

WSADATA为结构体,用于存储socket的内容,定义如下:

typedef struct WSAData {
        WORD                    wVersion;
        WORD                    wHighVersion;
#ifdef _WIN64
        unsigned short          iMaxSockets;
        unsigned short          iMaxUdpDg;
        char FAR *              lpVendorInfo;
        char                    szDescription[WSADESCRIPTION_LEN+1];
        char                    szSystemStatus[WSASYS_STATUS_LEN+1];
#else
        char                    szDescription[WSADESCRIPTION_LEN+1];
        char                    szSystemStatus[WSASYS_STATUS_LEN+1];
        unsigned short          iMaxSockets;
        unsigned short          iMaxUdpDg;
        char FAR *              lpVendorInfo;
#endif
} WSADATA

函数

int WSAStartup(
  __in          WORD wVersionRequested,
  __out         LPWSADATA lpWSAData
);

TheWSAStartupfunctioninitiatesuseoftheWinsockDLLbyaprocess.

Parameters

wVersionRequested

ThehighestversionofWindowsSocketsspecificationthatthecallercanuse.Thehigh-orderbytespecifiestheminorversionnumber;thelow-orderbytespecifiesthemajorversionnumber.

ReturnValue

Ifsuccessful,theWSAStartupfunctionreturnszero.Otherwise,itreturnsoneoftheerrorcodeslistedbelow.TheWSAStartupfunctiondirectlyreturnstheextendederrorcodeinthereturnvalueforthisfunction.AcalltotheWSAGetLastErrorfunctionisnotneededandshouldnotbeused.

Errorcode

Meaning
WSASYSNOTREADY Theunderlyingnetworksubsystemisnotreadyfornetworkcommunication.
WSAVERNOTSUPPORTED TheversionofWindowsSocketssupportrequestedisnotprovidedbythisparticularWindowsSocketsimplementation.
WSAEINPROGRESS AblockingWindowsSockets1.1operationisinprogress.
WSAEPROCLIM AlimitonthenumberoftaskssupportedbytheWindowsSocketsimplementationhasbeenreached.
WSAEFAULT ThelpWSADataparameterisnotavalidpointer.

Requirements

Client RequiresWindowsVista,WindowsXP,Windows2000Professional,WindowsNTWorkstation,WindowsMe,Windows98,orWindows95.
Server RequiresWindowsServer2008,WindowsServer2003,Windows2000Server,orWindowsNTServer.
Header DeclaredinWinsock2.h.
Library UseWs2_32.lib.
DLL RequiresWs2_32.dll.

连接准备

//创建客户端套接字
    SOCKET client=socket(AF_INET,SOCK_STREAM,0);//流式套接字。(数据报套接字,原套接字)
 SOCKADDR_IN svr_addr_in;//保存服务器端的地址信息
 svr_addr_in.sin_family=AF_INET;//代表TCP/IP协议族
 //inet_addr()把字符串变成无符号的长整型。获取服务器地址.0.0.1:本机做服务器,127.0.0.1是服务器的ip地址
 svr_addr_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
 //htons本函数将一个位数从主机字节顺序转换成网络字节顺序,该端口号要与服务器的端口号相同
 svr_addr_in.sin_port=htons(6000);
 while(connect(client,(sockaddr*)&svr_addr_in,sizeof(svr_addr_in))!=0);//链接服务器,等于表示连上服务器

SOCKET为重定义变量,原始变量类型为_W64unsignedint.

函数

SOCKET WSAAPI socket(
  __in          int af,
  __in          int type,
  __in          int protocol
);

Thesocketfunctioncreatesasocketthatisboundtoaspecifictransportserviceprovider.

结构体SOCKADDR_IN

struct sockaddr_in{
short sin_family;	//Address family (must be AF_INET).
unsigned short sin_port;	//IP port.
struct in_addr sin_addr;	//IP address.
char sin_zero[8];	//Padding to make structure the same size as SOCKADDR.
};

Theconnectfunctionestablishesaconnectiontoaspecifiedsocket.

int connect(
__in  SOCKET s,	//Descriptor identifying an unconnected socket.
__in  const struct sockaddr* name,//Name of the socket in the sockaddr structure to which the connection should be established.
  __in int namelen	//Length of name, in bytes.
);

监听准备

SOCKET svr=socket(AF_INET,SOCK_STREAM,0);
 SOCKADDR_IN svr_addr_in;//创建一个服务器地址结构体,用于保存服务器的信息
 svr_addr_in.sin_family=AF_INET;//协议家族
 svr_addr_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//htonl(INADDR_ANY);//获取当前机子网卡ip地址
 svr_addr_in.sin_port=htons(6000);//设置端口地址
    bind(svr,(sockaddr*)&svr_addr_in,sizeof(SOCKADDR_IN));//将socket绑定到本地机地址上面
 //把服务器socket设置为监听socket,同时能监听个client客服
 listen(svr,5);

bind函数

bind(
    IN SOCKET s,
    __in_bcount(namelen) const struct sockaddr FAR * name,
    IN int namelen
    );

Thelistenfunctionplacesasocketinastateinwhichitislisteningforanincomingconnection.

int listen(
  __in     SOCKET s,	//Descriptor identifying a bound, unconnected socket.
  __in     int backlog	//允许的最多的连接队列
);

发送数据

    SOCKADDR_IN client_addr_in;//用于保存客户端的信息
 int len=sizeof(SOCKADDR_IN);
    SOCKET client=accept(svr,(sockaddr*)&client_addr_in,&len);//等待(接受)客户端请求到来
 char b[1024]="ss";
 for(int i=0;;i++)
 {
 send(client,b,sizeof(b),0);//向服务器发送数据
 //system("pause"):
 }

接收数据

char b[1024];
 for(int i=0;;i++)
 {
 recv(client,b,sizeof(b),0);//客户端接受文件
  printf("%s",b);
 }

sendrecv函数的参数表都是

IN SOCKET s,	// The descriptor that identifies a connected socket.
__out_bcount_part(len, return) __out_data_source(NETWORK) char FAR * buf,
// The buffer for incoming data.
IN int len,// The length, in bytes, of the buf parameter.
IN int flags
//A pointer to flags that influences the behavior of this function. See remarks below.

善后处理

closesocket(client);//关闭客户端套接字
closesocket(svr);//关闭服务器套接字
WSACleanup();//卸载winsock动态链接库
Tagged with: , ,

发表评论

邮箱地址不会被公开。 必填项已用*标注

*