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);
}
send与recv函数的参数表都是
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动态链接库
发表回复