下面给出一个简单的select模型的服务端套接字,非阻塞模式。连接1个客户端,接收100MB数据后,返回OK退出。
//服务端,接收端
int SelectTcpRecver1()
{
SOCKET sListen, sClient;
int iAddrSize;
//HANDLE hThread;DWORD dwThreadId;
struct sockaddr_in local, client;
iAddrSize = sizeof(client);
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sListen == SOCKET_ERROR)
{
printf("socket() failed: %d\n", WSAGetLastError());
return 1;
}
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(TCPSERVER_PORT);
if (bind(sListen, (struct sockaddr *)&local,
sizeof(local)) == SOCKET_ERROR)
{
printf("bind() failed: %d\n", WSAGetLastError());
return -11;
}
if (listen(sListen, 8))
{
printf("listen Error:%d\n", WSAGetLastError());
return -2;
}
//ULONG NonBlock = 1;
//if (ioctlsocket(sListen, FIONBIO, &NonBlock) == SOCKET_ERROR){
// printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
// return -3;
//}
printf("进入监听状态\n");
int loopi = 0;
timeval tv;
FD_SET SelectSet;
while (1)
{
FD_ZERO(&SelectSet);//初始化fd_set
FD_SET(sListen, &SelectSet);//分配套接字句柄到相应的fd_set
tv.tv_sec = 2;//这里我们打算让select等待两秒后返回,避免被锁死,也避免马上返回
tv.tv_usec = 0;
select(0, &SelectSet, NULL, NULL, &tv);
loopi++;
if (FD_ISSET(sListen, &SelectSet))//如果套接字句柄还在fd_set里,说明客户端已经有connect的请求发过来了,马上可以accept成功
{
sClient = accept(sListen, (struct sockaddr *)&client, &iAddrSize);
if (sClient == INVALID_SOCKET){
printf("accept() failed: %d\n", WSAGetLastError());
break;
}
else
{
printf("Accepted client: %s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
break;
}
}
else//还没有客户端的connect请求,我们可以去做别的事,避免像没有用select方式的阻塞套接字程序被锁死的情况,如果没用select,当程序运行到accept的时候客户端恰好没有connect请求,那么程序就会被锁死,做不了任何事情
{
printf("wait ......%d\r",loopi);
//::MessageBox(NULL, "waiting...", "recv", MB_ICONINFORMATION);//别的事做完后,继续去检查是否有客户端连接请求
}
}
char * Buffer = (char *)malloc(MB100);
if (NULL == Buffer)
{
printf("100MB 内存分配失败!\n");
return -1;
}
DWORD nRemainRecv = MB100;
char * pBuf = (char *)Buffer;
int len,ret;
//接收100MB的数据
while (nRemainRecv > 0)
{
len = recv(sClient, pBuf, nRemainRecv, 0);
if (len < 0){
printf("Recv HeadDate Fail:%d\n", len);
break;
}
else if (len == 0){
printf("Pre len is 0 client quit!\n");
break;
}
printf("接收数据:%d\n", len);
nRemainRecv -= len;
pBuf += len;
}
free(Buffer);
printf("共接收数据:%d\n", MB100);
char szBuff[8];
sprintf_s(szBuff, _countof(szBuff), "%s", "OK");
ret = send(sClient, szBuff, (int)strlen(szBuff), 0);
if (ret == 0)printf("send 0\n");
else if (ret == SOCKET_ERROR)
{
printf("send() failed: %d\n", WSAGetLastError());
}
closesocket(sClient);
closesocket(sListen);
return 0;
}
发送端:
int TcpSender()
{
SOCKET sClient;
int ret;
struct sockaddr_in server;
struct hostent *host = NULL;
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sClient == INVALID_SOCKET)
{
printf("socket() failed: %d\n", WSAGetLastError());
return 1;
}
ZeroMemory(&server, sizeof(sockaddr_in));
server.sin_family = AF_INET;
server.sin_port = htons(TCPSERVER_PORT);
server.sin_addr.s_addr = inet_addr(ServerIp);
if (server.sin_addr.s_addr == INADDR_NONE)
{
host = gethostbyname(ServerIp);
if (host == NULL)
{
printf("Unable to resolve server: %s\n", ServerIp);
return 1;
}
CopyMemory(&server.sin_addr, host->h_addr_list[0],host->h_length);
}
printf("We are trying to connect to %s:%d...\n", inet_ntoa(server.sin_addr), htons(server.sin_port));
if (connect(sClient, (struct sockaddr *)&server,sizeof(server)) == SOCKET_ERROR)
{
printf("connect() failed: %d\n", WSAGetLastError());
return 1;
}
//准备发送100MB的数据
char * Buffer = (char *)malloc(MB100);
if (NULL == Buffer)
{
printf("100MB 内存分配失败!\n");
return -1;
}
memset(Buffer, '#', MB100);
int nLeft = MB100;
int idx = 0;
DWORD lt1, lt2,lt;
int i = 0;
lt1 = timeGetTime();
//int len1 = 65535;
while (nLeft > 0)
{
lt2 = timeGetTime();
/* if (nLeft > len1)len1 = 65536;
else len1 = nLeft;*/
//Sleep(5);
ret = send(sClient, &Buffer[idx], nLeft, 0);
if (ret == 0){
printf("send is 0,%d\n", WSAGetLastError());
break;
}
else if (ret == SOCKET_ERROR)
{
printf("send() failed: %d\n", WSAGetLastError());
break;
}
lt = timeGetTime() - lt2;
//if(lt > 50)
printf("i:%d,Send %d bytes,耗时:%d\n",i, ret,lt);
i++;
nLeft -= ret;
idx += ret;
}
printf("100MB 发送完成:%d\n", timeGetTime() - lt1);
//接收确认的信息
char szBuf[8];
ret = recv(sClient, szBuf, sizeof(szBuf), 0);
if (ret == 0){
printf(" Graceful close\n");
}
else if (ret == SOCKET_ERROR)
{
printf("recv() failed: %d,共计消耗时间%d\n", WSAGetLastError(),timeGetTime() - lt2);
}
else
{
szBuf[ret] = '\0';
printf("RECV [%d bytes]: '%s'\n", ret, szBuf);
printf("接收确认信息:%d\n", timeGetTime() - lt2);
}
free(Buffer);
closesocket(sClient);
return 0;
}