windows sockets TCP基础函数及范例

 

准备工作:
1 导入头文件winsock2.h
2 链接ws2_32.lib
3 调用WSAStartup(WORD wVersionRequested,LPWSADATA lpwsaData);
说明:
1 成功时返回0,失败时返回非零的错误代码值
2 wVersionRequested:程序员要使用的Winsock版本信息。高八位为副版本号,低八位为主版本号
常用MAKEWORD宏来函数构建:MAKEWORD(1,2):主版本为1,副版本为2,返回0x0201。
3 lpwsaData:WSADATA结构体变量的地址值

 

作用是在相应参数中填充已经初始化的库信息。

初始化公式:

 

int main(int argc,char* argv[])//argc是命令行总的参数个数 ,argv[]里记录了用户输入的参数,其中第0个参数是程序的全名
{
	WSADATA wsaData;
	……
	if(WSAStartup(MAKEWORD(2,2),&wsaData)! = 0
		ErrorHandling("WSAStartup() error!");
	……
	return 0;
	
}
#include
SOCKET socket(int af,int type,int protocol);

说明:
1 成功时返回套接字句柄,失败时返回INVALID_SOCKET
2 int af:协议族信息,对于TCP/IP协议的套接字,它只能是AF_INET(也可以写成PF_INET)
3 int type:套接字类型,SOCK_STREAM/SOCK_DGRAM
4 int protocol:最终决定的协议,一般情况下为0,即系统选择

服务器:

 

 

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

说明:
1 成功时返回0,失败时返回SOCKET_ERROR.
2 SOCKET s:由socket函数返回的套接字句柄
3 const struct sockaddr * name:sockaddr_in 结构指针,指向赋给套接字的本地地址
sockaddr_in.family:协议族
sockaddr_in.sin_addr.S_addr:地址,若为htonl(INADDR_ANY),则表示程序不关心分配的地址
sockaddr_in.sin_port :端口,若为 htons(nServPort),则随意分配一个1024——5000之间的端口
4 int namelen: sockaddr结构的长度

用法演示:

 

 

	SOCKET s;
	struct sockaddr_in servAddr;
	int nServPort = 5500;
	int nErrCode;
	
	servAddr.family = AF_INET;
	servAddr.sin_addr.S_addr = htonl(INADDR_ANY);
	servAddr.sin_port = htons(nServPort);
	
	nErrCode = bind(s,(sockaddr *)&servAddr,sizeof(servAddr));
	if(SOCKET_ERROR == nErrCode)
	{
		//绑定套接字失败
	}

 

 

int listen(SOCKET s,int backlog);

说明:
1 成功时返回0,失败时返回SOCKET_ERROR
2 SOCKET s:由socket函数返回IDE套接字句柄
3 int backlog:知道等待连接的最大队列长度
 

SOCKET accept(SOCKET s,struct sockaddr *addr,int * addrlen);

说明:
1 成功则返回一个新的套接字句柄,失败则返回INVALID_SOCKET
2 SOCKET s:监听套接字
3 struct sockaddr *addr :返回客户端的地址信息
4 int * addrlen:返回sockaddr结构体长度

 

用法演示:

 

	SOCKET sListen;
	SOCKET sAccept;
	sockaddr_in addrClient;
	
	int addrClientlen = sizeof(addrClient);
	
	sAccept = accept(sListen,(sockaddr *)&addrClient,&addrClientlen);
	if(INVALID_SOCKET == sAccept)
	{
		//失败处理
	}

 

 

int closesocket(SOCKET s);

说明:
1 关闭套接字,成功时返回0,失败时返回SOCKET_ERROR

 

int recv(SOCKET s,char FAR* buf,int len,int flags);

说明:
1 用于接受数据,成功时返回接受的字节数,失败时返回SOCKET_ERROR。
2 SOCKET s:接受套接字
3 char FAR* buf:接受数据缓冲区
4 int len:缓冲区长度
5 int flags:该参数影响该函数的行为。
取值为0:表示无特殊行为
取值为MSG_PEEK:使有用的数据被复制到接受缓冲区内,但没有从系统缓冲区删除
取值为MSG_OOB: 表示处理带外数据
用法演示:

 

 

	SOCKET s;
	char buf[128];
	int nReadLen;
	
	nReadLen = recv(s,buf[128],128,0);
	if(SOCKET_ERROR == nReadLen)
	{
		//失败处理
	}


客户端: 

 

 

int connect(SOCKET s,const struct sockaddr *name,int namelen);

说明:
1 成功时返回0,失败时返回SOCKET_ERROR
2 SOCKET s:由socket函数返回的套接字句柄
3 const struct sockaddr *name:服务器地址
4 int namelen:sockaddr结构体长度

注:
htonl:host to net long int 将主机的无符号长整型数转换为网络字节顺序
htons: host to net short int 将主机的无符号短整型数转换为网络字节顺序

实例演示:
该实例通过客户端向服务器发送“MyTCP”字符串,服务器接收该字符串并显示出来。
客户端发送后退出,服务器显示后退出。

 

windows sockets TCP基础函数及范例_第1张图片

 

//Server:
	WSADATA wsd;
	SOCKET sServer;
	int retVal;
	
	//初始化套接字动态库
	if(WSAStartup(MAKEWORD(2,2),&wsd) != 0)
	{
		printf("WSAStartup failed!\n");
		return 1;
	}
	
	//创建套接字
	sServer = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(INVALID_SOCKET == sServer)
	{
		printf("socket failed!");
		WSACleanup();		//释放套接字资源
		return -1;
	}
	
	//绑定套接字
	SOCKADDR_IN addrServ;	//服务器地址
	
	addrServ.sin_family = AF_INET;
	addrServ.sin_port = htons(4999);
	addrServ.sin_addr.s_addr = INADDR_ANY;
	
	retVal = bind(sServer,(SOCKADDR *)&addrServ,sizeof(SOCKADDR_IN));
	
	if(SOCKET_ERROR == retVal)
	{
		printf("bind failed!\n");
		closesocket(sServer);	//关闭套接字
		WSACleanup();
		return -1;
	}
	
	//监听
	retVal = listen(sServer,1);
	if(SOCKET_ERROR == retVal)
	{
		printf("listen failed!\n");
		closesocket(sServer);
		WSACleanup();
		return -1:
	}
	
	//等待客户端连接
	SOCKET sClient;
	sockaddr_in addrClient;
	int addrClientlen = sizeof(addrClient);
	sClient = accept(sServer,(sockaddr *)&addrClient,&addrClientlen);
	if(INVALID_SOCKET == sClient)
	{
		printf("accept failed!\n");
		closesocket(sServer);
		WSACleanup();
		return -1;
	}
	
	//接受并显示数据
	#define BUF_SIZE 64
	ZeroMemory(buf,BUF_SIZE);	//将接受缓冲区清0
	retVal = recv(sClient,buf,BUF_SIZE,0);
	if(SOCKET_ERROR == retVal)
	{
		printf("recv failed!\n");
		closesocket(sServer);
		WSACleanup();
		return -1;
	}
	printf("%s \n",buf);
	
	//退出
	closesocket(sServer);
	closesocket(sClient);
	WSACleanup();

 

 

//Client:
	#define BUF_SIZE 64
	WSADATA wsd;
	SOCKET sHost;	//服务器套接字
	SOCKADDR_IN servAddr;	//服务器地址
	char buf[BUF_SIZE];
	int retVal;
	
	//初始化套接字动态库
	if(WSAStartup(MAKEWORD(2,2),&wsd) != 0)
	{
		printf("WSAStartup failed!\n");
		return -1;
	}
	
	//创建套接字
	sHost = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(INADDR_SOCKET == sHost)
	{
		printf("socket failed!\n");
		WSACleanup();
		return -1;
	}
	
	//连接服务器
	sevrAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	servAddr.sin_port = htons((short)4999);
	int nServAddlen = sizeof(servAddr);
	
	retVal = connect(sHost,(LPSOCKADDR)&servAddr,nServAddlen);
	if(SOCKET_ERROR == retVal)
	{
		printf("connect failed!\n");
		closesocket(sHost);
		WSACleanup();
		return -1;
	}
	
	//发送数据
	ZeroMemory(buf,BUF_SIZE);
	stpcpy(buf,"MyTcp");
	retVal = send(sHost,buf,strlen(buf),0);
	if(SOCKET_ERROR == retVal)
	{
		printf("send failed! \n");
		closesocket(sHost);
		WSACleanup();
		return -1;
	}
	
	//退出
	closesocket(sHost);
	WSACleanup();

参考《精通Windows Sockets 网络开发 ——基于Visual C++ 实现》 --孙海民

 

 

 

 

 

 

 

你可能感兴趣的:(vc++/c++/mfc学习)