本文学习相关资料:
C/C++ socket编程教程
环境:vs2015
源码:本文代码
windows 如何创建客户端与服务端通信?
TCP:
服务端
在windows先告诉程序我们要使用哪个版本的winsock,成功调用了它才能继续下去
#pragma comment (lib,"ws2_32.lib") //连接ws2_32.lib
/*
MAKEWORD(2,2)表示使用2.2版本的
WSA:Windows Socket API
Startup:启动
*/
WSADATA wsadata;
WSAStartup(MAKEWORD(2, 2), &wsadata)
然后是创建一个套接字:
/*
这样就创建了一个套接字了
PF_INET:表示使用ipv4
SOCK_STREAM:表示使用面向连接的数据传输方式
IPROTO_TCP:表示使用TCP协议
*/
SOCKET servSock = SOCKET(PF_INET,SOCK_STREAM, IPPROTO_TCP);
然后创建sockaddr_in,用来将上面socket和ip地址、端口绑定
/*
sockaddr_in 是一个结构体
sin_family:使用了ipv4地址
sin_addr.s_add:要绑定的ip地址
sin_port:要绑定的端口inet_addr():将ip地址从字符串转为整数,每个32位的ip地址都有一个对应的整数
htons():将整型变量从主机字节顺序转变成网络字节顺序
每台电脑可能由于系统或配置差异导致字节顺序不同,这时大家协商好网络字节的顺序,
在通信前先将自己的字节顺序转成网络字节顺序,再发送;
在接受到信息后再转回自己的字节顺序。*/
sockaddr_in servAddr;
servAddr.sin_family = AF_INET;
//servAddr.sin_addr.s_add = inet_addr("127.0.0.1");
//要使用inet_pton需要包括头文件:WS2tcpip.h
//这里使用inet_pton来填写IP地址的原因是vs2015整天告诉我说inet_addr不安全
inet_pton(AF_INET,"127.0.0.1", &sockAddr.sin_addr.s_addr); //说明要监听的ip地址servAddr.sin_port = htons(9000);/*
这里第二个参数是SOCKADDR*类型的,结构和sockaddr_in类似
*///绑定
bind(servSock,(SOCKADDR*)&sockAddr,sizeof(SOCKADDR));
现在将端口和IP地址都绑定好了,可以开始监听有没有人要连接这个端口了
/*
第一个参数表示用来监听的套接字
第二个参数表示队列长度,来访问的人都在这个队列里面,等待接收
*/listen(servSock,20);
现在有客户端发来连接请求了,要怎么接受连接呢
/*
accept 取出队列的第一个连接请求
第一个参数:在listen的那个socket
第二个参数:客户端的IP地址和端口
第三个参数:SOCKADDR的大小*/
int nSize = sizeof(SOCKADDR);
socketaddr_in clnAddr;
SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize)
那现在成功接受请求了,那么要怎么接收发送的数据呢?
/*
recv 接收客户端发来的数据,默认是阻塞的(也就是程序会一直等到客户端发信息来,否则不会往下执行)
第一个参数:accept时候返回的套接字
第二个参数:数据保存的地方
第三个参数:读取数据的最大长度(字节)
返回值:实际读取了多少个字节的数据
*/
int maxlen = 200;
char buf[maxlen]
int len = recv(clntSock, buf, maxlen, 0)
好了现在服务端接收到关闭的信息了,要怎么关闭呢
/*
记得都要关闭哦
CleanUp:清理
*/
closesocket(clntSock);
closesocket(servSock);
WSACleanup();
客户端
前面和服务端类似,都是需要创建套接字,说明服务端的IP地址和端口
记得在这前面要说明使用的socket 版本哦
SOCKET client = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(sockaddr_in));
servAddr.sin_family = PF_INET;
//servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
inet_pton(AF_INET,"127.0.0.1", &servAddr.sin_addr.s_addr); //说明要监听的ip地址
servAddr.sin_port = htons(9000);
然后可以开始连接了
/*
这个和bind函数类似,只不过那个是绑定,这个连接,连接成功是返回0,否则返回-1
*/
connect(client, (sockaddr*)&servAddr, sizeof(sockaddr_in));
好的,现在客户端连接上了,是时候发送信息过去了
/*
send
第一个参数:连接成功的那个套接字
第二个参数:发送的内容
第三个参数:发送的内容长度
第四个参数:??
*/
send(client,"Hello Server",13,0);
好了,信息发过去了,我这边也要关闭了
closesocket(client);
WSACleanup();