TCP,传输控制协议,是一种面向连接可靠的传输层协议,面向连接指的是一次正常的TCP传输需要通过在TCP服务器端和客户端之间建立虚电路,TCP客户端和服务端需要建立连接。
Winsock C/S模型中服务器的建立过程是1,初始化WSA 2.建立一个SOCKET 3.绑定SOCKET 4指定监听端口,5接受连接,发送接收数据6断开连接
这个过程需要用到的API有:
1. WSADATA 它是AfxSocketInit返回的函数,WSAStartup可以给WSADATA结构的成员分配值,
2. WORD mVersionRequested参数用于指定准备加载的winsock库版本,
3. MAKEWORD的原型是 WORD MAKEWORD(BYTE blow,BYTE high),其中的blow代表新变量的低字节序,high代表新变量的高字节。它把两个字节合成为一个字,长度为16,类型为无符号整形数。
4. Socket函数原型为 int socket(int domain,int type,int protocol)第一个参数指定应用程序使用的通信协议的协议簇,TCP/IP的参数设置为AF_INET。第二个参数指定要创建的套接字类型,如果是流套接字,该参数设置为SOCK_STREAM ,如果是数据报套接字,该参数设置为SOCK_DGRAM,第三个参数一般取0,系统根据套接字的类型决定应使用的传输层协议。
5. SOCKADDR_IN的原型为
6. Struct sockaddr_in {
Short sin_family; 地址族,一般为AF_INET
U_short sin_port; 指定端口
Struct in_addr sin_addr; 主机IP地址
Char sin_zero[8]; 填充数
}
7. accept函数原型为 SOCKET accept(SOCKET s,struct sockaddr* addr,int *addrlen)
SOCKET s 指定处于监听状态的套接字, struct sockaddr* addr,用来接收连接实体的地址,保存客户端的IP地址 int *addr 用来包含返回地址的长度
8.recv 函数的原型为int recv(SOCKET s,char FAR *buf,int len,int flags)
不论是客户端还是服务器端,都要用recv从TCP连接的另外一端接收数据,第一个参数指明接收端套接字描述符,第二个参数指明一个缓冲区,第三个参数指明缓冲区的长度,第四个参数一般置为0.
下面是服务器端的代码:
#include <Winsock2.h> #include <stdio.h> #include <iostream> using namespace std; #pragma comment(lib,"ws2_32.lib") void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { cout<<"error"<<endl; //初始化出现错误 return; } if ( LOBYTE( wsaData.wVersion ) != 2 || //LOBYTE 用于取低字节 HIBYTE( wsaData.wVersion ) != 2 ) { //HIBYTE 用于取高字节 WSACleanup( ); return; } SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);//创建socket连接 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); listen(sockSrv,5); SOCKADDR_IN addrClient; int len=sizeof(SOCKADDR); SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);//等待客户端的连接 char recvBuf[100]; printf("IP %s is connecting\n\n",inet_ntoa(addrClient.sin_addr)); while(1) { recv(sockConn,recvBuf,sizeof(recvBuf),0); printf("客户端消息:"); printf(recvBuf); printf("\n\n"); } closesocket(sockConn); //关闭 }
客户端的建立过程是:1初始化WSA2建立socket3连接到服务器4发送和接收数据5断开连接
下面是客户端的代码:
#include <Winsock2.h> #include <stdio.h> #include <iostream> using namespace std; #pragma comment(lib,"ws2_32.lib") void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { WSACleanup( ); 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"); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); while(1) { char sendBuf[100]; printf("plese input your word: "); cin.getline(sendBuf,99); send(sockClient,sendBuf,strlen(sendBuf)+1,0); printf("\n\n"); } closesocket(sockClient); WSACleanup(); }