说明:
本程序是基于windows socket的套接字库实现网络编程;
当WSAStartup函数调用成功后,在程序的最后都需要相应的调用WSACleanup函数
以便释放为该应用程序分配的资源,终止对WinSock动态库的使用。
基于TCP的服务器端流程
- 创建套接字(socket);
- 将socket绑定本地地址和端口号(bind);
- 将 socket设置为监听模式,准备接收客户端请求(listen);
- 等待客户请求到来;当请求到来后,返回一个新的对应于此次连接的socket(accept);
- 用返回的socket和客户端进行通信(send/recv);
- 返回,等待另一个客户请求;
- 关闭socket;
服务器端流程:
代码如下:
// TCPSrv.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <WinSock2.h>
int _tmain(int argc, _TCHAR* argv[])
{
//加载套接字库
WORD wVersionRequested;
WSADATA wsaData = {0};
wVersionRequested = MAKEWORD(1,1);
if (WSAStartup(wVersionRequested, &wsaData) != 0 )
{
return 1;
}
if (LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup( );
return 1;
}
//The WinSock DLL is acceptable.
//创建用于监听的套接字,拥有地址族 但是没有名字:地址族+地址+端口号
SOCKET socketSrv = socket(AF_INET, SOCK_STREAM,0);
//创建服务器端名字信息
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//地址
addrSrv.sin_family = AF_INET;//地址族
addrSrv.sin_port = htons(6000);//端口号
//将名字和套接字绑定在一起
bind(socketSrv,(SOCKADDR*)&addrSrv, sizeof(SOCKADDR_IN));
//将套接字设为监听模式,准备接收客户请求
listen(socketSrv,SOMAXCONN);
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
while (1)
{
//accpet会阻塞,直到client端调用connect
SOCKET sockConn = accept(socketSrv,(SOCKADDR*)&addrClient,&len);
//发送数据
char sendBuf[100] = {"this is server."};
send(sockConn,sendBuf, strlen(sendBuf),0);
//接收数据
char recvBuf[100] = {0};
recv(sockConn,recvBuf,sizeof(char)*100,0/*一般设置为0*/);
//打印接收数据
printf("recv data:%s
",recvBuf);
//关闭套接字
closesocket(sockConn);
}
//关闭监听套接字
closesocket(socketSrv);
//清理套接字库的使用
WSACleanup();
return 0;
}
基于TCP的客户端流程
- 创建套接字(socket);
- 向服务器发起请求(connect);
- 和服务器进行通信(send/recv);
- 关闭套接字;
客户端端流程:
代码如下:
// TcpClient.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <WinSock2.h>
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
//加载套接字库
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup(wVersionRequested, &wsaData);
if ( err != 0 )
{
return 1;
}
if (LOBYTE(wsaData.wVersion) != 1
||HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup();
return -1;
}
//创建客户端的套接字
SOCKET sockClient = socket(AF_INET,SOCK_STREAM, 0/*自动选择协议*/);
//设定服务器端地址和端口
SOCKADDR_IN addrSrv;
//客户端和服务器均在一台电脑上
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addrSrv.sin_family = AF_INET;
//和服务器的端口号一致
addrSrv.sin_port = htons(6000);
//向服务器发送请求
connect(sockClient, (SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
//接收数据
char recvBuf[100] = {0};
recv(sockClient,(char*)recvBuf,sizeof(char)*100,0);
printf("recv data:%s
", recvBuf);
//发送数据
char sendBuf[100]= {"this is client."};
send(sockClient,sendBuf,strlen(sendBuf),0);
//关闭套接字,释放和套接字相关的资源
closesocket(sockClient);
//终止对套接字库的使用
WSACleanup();
system("pause");
return 0;
}
测试结果:
可以有多个客户端可以向服务器端发起请求,服务器一个个接收请求;