侦听函数将套接字置于侦听传入连接的状态。
int WSAAPI listen(
[in] SOCKET s,
[in] int backlog
);
参数
[in] s
标识绑定的未连接的套接字的描述符。
[in] backlog
挂起的连接队列的最大长度。 如果设置为 SOMAXCONN,则负责套接字 的基础 服务提供商会将积压工作设置为最大合理值。
返回值
如果未发生错误, 则侦听 返回零。 否则,将返回 值 SOCKET_ERROR ,并且可以通过调用 WSAGetLastError 来检索特定的错误代码。
backlog的意义,
在listen()后,accept()以前,最大的链接数目,因为是队列,先进先出,只要前面的不结束,后面的就链接不了。
代码
TCPServer
#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main()
{
cout << "TCPServer Start!!!" << endl;
//0 初始化网络化库
WORD WVersionRequested;
WSADATA wsaData;
int err;
WVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(WVersionRequested, &wsaData);
if (err != 0)
{
printf("WSAStartup errorNum = %d\n", GetLastError());
return err;
}
if (LOBYTE(wsaData.wVersion) != 2,HIBYTE(wsaData.wVersion) != 2)
{
printf("LOBYTE errorNum = %d\n", GetLastError());
WSACleanup();
return -1;
}
//1 建立socket(安装电话机)
SOCKET socketServer = socket(AF_INET, SOCK_STREAM, 0);
//2 分配电话号码 设置参数
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_port = (6000);
if (SOCKET_ERROR== bind(socketServer, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)))
{
printf("bind errorNo=%d\n", GetLastError());
return -1;
}
//3 监听
if (SOCKET_ERROR== listen(socketServer, 5))
{
printf("listen errorNo=%d\n", GetLastError());
return -1;
}
// 创建条件,构成listen后,accept前
printf("delay start\n");
Sleep(20000);
printf("delay end\n");
SOCKADDR_IN addrCli;
int len = sizeof(addrCli);
while (TRUE)
{
//4 分配电话分机
printf("start accept\n");
SOCKET sockConn = accept(socketServer, (SOCKADDR*)&addrCli, &len);
printf("end accept\n");
char sendBuf[100] = {0};
//sprintf_s(sendBuf, 100, "hello");
sprintf_s(sendBuf, 100, "Welcome %s to China!!", inet_ntoa(addrCli.sin_addr));
//5 开始通话 进行收发数据
int iLen=send(sockConn, sendBuf, sizeof(sendBuf), 0);
char recvBuf[100] = {0};
iLen = recv(sockConn, recvBuf, 100, 0);
printf("RecvBuf=%s\n", recvBuf);
//6 关闭分机
closesocket(sockConn);
}
// 7 关闭总机
closesocket(socketServer);
WSACleanup();
system("pause");
return 0;
}
TCPClient
#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main()
{
cout << "TCPClient Start!!!" << endl;
//初始化网络化库
WORD WVersionRequested;
WSADATA wsaData;
int err;
WVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(WVersionRequested, &wsaData);
if (err != 0)
{
printf("WSAStartup errorNum = %d\n", GetLastError());
return err;
}
if (LOBYTE(wsaData.wVersion) != 2, HIBYTE(wsaData.wVersion) != 2)
{
printf("LOBYTE errorNum = %d\n", GetLastError());
WSACleanup();
return -1;
}
//1 建立socket(安装电话机)
SOCKET socketCli = socket(AF_INET, SOCK_STREAM, 0);
//2 配置要链接的服务器 设置参数
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;
addrSrv.sin_addr.S_un.S_addr = inet_addr("你自己要链接的ipv地址");
addrSrv.sin_port = (6000);
//3 连接服务器
if (SOCKET_ERROR==connect(socketCli,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)))
{
printf("connect errorNo=%d\n", GetLastError());
system("pause");
return -1;
}
//4 收发数据
char recvBuf[100] = { 0 };
int iLen = recv(socketCli, recvBuf, 100, 0);
printf("recvBuf=%s", recvBuf);
char sendBuf[100] = "我是sb";
iLen = send(socketCli, sendBuf, 100, 0);
//5 关闭套接字
closesocket(socketCli);
WSACleanup();
system("pause");
return 0;
}
将这两代码编译运行,会发现,在创建第六个链接的时候会报错,因为,我们设置的最大链接数是5;所以在前面五个没有断开链接前,后面的都会连接失败。
读者注意:这里的5,指的不是最大的链接的数目,只是指在listen后accept前,这中间的时间,里面最后有五个链接,后面的链接会被拒绝。等到了accept后,最大链接具体是多少我不知道,但我创建了十几个。