void main() {
WORD wVersionRequested;
//定义一个word类型的变量,用于指定准备加载的winsock库的版本 WSADATA wsaData;
//定义一个WSADATA类型的结构体变量,用以加载套接字库,并指定连接的版本号
int err;
wVersionRequested = MAKEWORD(1,1);//请求一个1.1版本的套接字库
err = WSAStartup( wVersionRequested,&wsaData );
//请求加载,如winsock没有正确初始化或者没有被找到,则返回“WSASYS NOT READY”
if ( err != 0 ){ return; }
//初始化失败,则退出程序
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ){ WSACleanup(); return; }
//winsock初始化成功后判断版本号(高字节+低字节)是否与请求版本号相同,如不相同,则停止调用
SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0); /*创建一个套接字socket(AF_INET,SOCK_STREAM,0);第一个参数用来指定地址族,
对于TCP/IP协议的套接字,它只能是AF_INET(PF_INET),第二个参数用来指定socket类型,
SOCK_STREAM指的是采用基于TCP/IP协议的套接字,SOCK_DGRAM为UDP协议的,第三个参数
是与特定的地址家族相关的协议,如果为0,则自动选择*/
//调用成功后会返回一个新的socket数据类型的套接字,需要绑定到本地的IP和端口
SOCKADDR_IN addrSrv;//定义一个地址结构体变量 addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
//获取本地任何一个可用IP地址,如需指定,则可调用inet_addr()函数 addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);//指定端口号,转换成2进制
bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //把套接字sockSrv绑定到本地的IP和端口
listen(sockSrv,5); //监听连接请求,5为最大等待连接数
SOCKADDR_IN addrClient; int len=sizeof(SOCKADDR);
//下面的循环为不断监听连接请求
while(1) { SOCKET
sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);
//接受客户机的连接请求并获取客户机的套接字等信息 bool flag=1;//定义一个开关变量,初始置开 while(flag)//循环用于维护当前连接的客户机 { //获取请求连接计算机的套接字,IP和端口号 char recvBuf[100];//定义一个字符数组,用来保存客户机传递过来的消息
recv(sockConn,recvBuf,100,0);//接受客户机信息 if(recvBuf[0]=='q')//如果客户机退出连接,则关闭socket连接 { flag=0;//开关置闭 closesocket(sockConn); continue; } printf(\"%s\\n\输出客户机发来的消息 char sendBuf[100];//用来存储发给客户机的消息 printf(\"Please input data:\\n\"); gets(sendBuf);//键盘输入 send(sockConn,sendBuf,strlen(sendBuf)+1,0);//把消息发给客户机
} } }
④ 添加动态链接库文件ws2_32.lib
⑤ 编译运行
2) 创建客户机端程序
① 在上面的项目中添加新的工程TCPclient
② 在该工程添加程序文件client.cpp
③ 分析下面程序,并复制到client.cpp文件中
#include #include void main() {
WORD wVersionRequested; WSADATA wsaData; int err;
wVersionRequested = MAKEWORD(1,1);
err = WSAStartup( wVersionRequested,&wsaData ); if ( err != 0 ){ return; }
SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr(\"127.0.0.1\");
//绑定需要连接的服务器的IP地址,127.0.0.1为本地本机地址 addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000);
connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //请求连接,进行TCP连接过程
//循环用来不断发送消息到服务器 while(1) {
char recvBuf[100];
printf(\"Please input data:\\n\"); gets(recvBuf);
send(sockClient,recvBuf,strlen(recvBuf)+1,0); //发送消息到服务器
if('q'==recvBuf[0])//按Q退出并关闭socket连接 {
closesocket(sockClient); WSACleanup(); break; }
recv(sockClient,recvBuf,100,0);//接收服务器消息 printf(\"%s\\n\ } }
④ 添加动态链接文件ws2_32.lib
⑤ 编译运行
3) 进行通信试验
① 先编译运行服务器端程序
② 编译运行客户端程序
③ 进行通讯试验
当客户端发消息的时候,服务器端会接收
当服务器端回复时,客户端也会接受
④ 在客户端输入‘q’退出,服务器继续监听新的连接
.2 课后总结
1. TCP和UDP的区别
TCP协议和UDP协议各有所长、各有所短,适用于不同要求的通信环境。
UDP和TCP协议的主要区别是两者在如何实现信息的可靠传递方面不同。TCP协议中包含了专门的传递保证机制,当数据接收方收到发送方传来的信息时,会自动向发送方发出确认消息;发送方只有在接收到该确认消息之后才继续传送其它信息,否则将一直等待直到收到确认信息为止。
与TCP不同,UDP协议并不提供数据传送的保证机制。如果在从发送方到接收方的传递过程中出现数据报的丢失,协议本身并不能做出任何检测或提示。因此,通常人们把UDP协议称为不可靠的传输协议。
相对于TCP协议,UDP协议的另外一个不同之处在于如何接收突法性的多个数据报。不同于TCP,UDP并不能确保数据的发送和接收顺序。