海南最低工资标准2017:Socket通信(TCP)非阻塞模式-select模型 — Windows Live
来源:百度文库 编辑:中财网 时间:2024/05/13 15:25:21
Socket通信(TCP)非阻塞模式-select模型
这个范例是个基于TCP协议的非阻塞模式下的SOCKET通信。应该非常具有代表性了,分为服务器端和客户端。非阻塞类型: Select模型 //////////////////////////////////////////////
// TCP Server select非阻塞模式
// IP: 127.0.0.1
// PORT: 1207
////////////////////////////////////////////#define LISTEN_IP "127.0.0.1"
#define LISTEN_PORT 1207
#define DEFAULT_BUFF 256
#define MAX_LISTEN 2 //最多可同时连接的客户端数量int g_fd_ArrayC[MAX_LISTEN] = {0}; //处理所有的待决连接int _tmain(int argc, _TCHAR* argv[])
{
WSAData wsData;
SOCKET sListen;
SOCKET sClient;
SOCKADDR_IN addrListen;
SOCKADDR_IN addrClient;
int addrClientLen = sizeof(addrClient);
char recvBuff[DEFAULT_BUFF] = {0};
char responseBuff[DEFAULT_BUFF] = {"Server Has Received"};
char noresponseBuff[DEFAULT_BUFF] = {"服务器端连接数已满,无法连接"};
int nRes = 0; printf(">>>>>TCP 服务器端启动<<<<<<\n");
WSAStartup(MAKEWORD(2,2), &wsData); printf("-创建一个SOCKET\n");
sListen = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if(sListen==INVALID_SOCKET)
{
printf("!!! socket failed: %d\n", WSAGetLastError());
WSACleanup();
return -1;
} printf("-设定服务器监听端口\n");
addrListen.sin_family = AF_INET;
addrListen.sin_addr.S_un.S_addr = inet_addr( LISTEN_IP );
addrListen.sin_port = htons( LISTEN_PORT ); printf("-绑定SOCKET与指定监听端口: %s:%d\n", inet_ntoa(addrListen.sin_addr), ntohs(addrListen.sin_port));
nRes = bind( sListen, (const sockaddr*)&addrListen, sizeof(addrListen) );
if( nRes == SOCKET_ERROR )
{
printf("!!! bind failed: %d\n", WSAGetLastError());
closesocket( sListen );
WSACleanup();
return -1;
} printf("-监听端口\n");
nRes = listen( sListen, MAX_LISTEN );
if( nRes == SOCKET_ERROR )
{
printf("!!! listen failed: %d\n", WSAGetLastError());
closesocket( sListen );
WSACleanup();
return -1;
} /////////////////////////////
// 非阻塞模式设定
//
/////////////////////////////
DWORD nMode = 1;
nRes = ioctlsocket( sListen, FIONBIO, &nMode );
if( nRes == SOCKET_ERROR )
{
printf("!!! ioctlsocket failed: %d\n", WSAGetLastError());
closesocket( sListen );
WSACleanup();
return -1;
}
printf("-设置服务器端模式: %s\n", nMode==0? "阻塞模式":"非阻塞模式");
printf("-开始准备接受连接\n");
fd_set fdRead;
fd_set fdWrite;
timeval tv={10,0};
int nLoopi = 0;
int nConnNum = 0;
while(true)
{
printf("-select 开始\n");
FD_ZERO(&fdRead, &fdWrite);
FD_SET( sListen, &fdRead ); //将待决的连接SOCKET放入fdRead集中进行select监听
for( nLoopi=0; nLoopi
if( g_fd_ArrayC[nLoopi] !=0 )
{
printf("-LOOPI: 待决SOCKET: %d\n",g_fd_ArrayC[nLoopi] );
FD_SET( g_fd_ArrayC[nLoopi], &fdRead );
}
} //调用select模式进行监听
nRes = select( 0, &fdRead, NULL, NULL, &tv );
;;;;;if( nRes == 0 )
{
printf("-!!! select timeout: %d sec\n",tv.tv_sec);
continue; //继续监听 }
else if( nRes < 0 )
{
printf("!!! select failed: %d\n", WSAGetLastError());
break;
}
//检查所有的可用SOCKET
printf("-查找可用的SOCKET\n");
for( nLoopi=0; nLoopi
if( FD_ISSET(g_fd_ArrayC[nLoopi], &fdRead) )
{
memset( recvBuff, 0 ,sizeof(recvBuff) );
nRes = recv( g_fd_ArrayC[nLoopi], recvBuff, sizeof(recvBuff)-1, 0 );
if( nRes <= 0 )
{
printf("-Client Has Closed.\n");
closesocket( g_fd_ArrayC[nLoopi] );
//将已经关闭的SOCKET从FD集中删除
FD_CLR( g_fd_ArrayC[nLoopi], &fdRead );
g_fd_ArrayC[nLoopi] = 0;
--nConnNum;
}
else
{
recvBuff[nRes] = '\0';
printf("-Recvied: %s\n", recvBuff); send( g_fd_ArrayC[nLoopi], responseBuff, strlen(responseBuff), 0 );
}
}
}//for( nLoopi=0; nLoopi
if( FD_ISSET( sListen, &fdRead) )
{
printf("-发现一个新的客户连接\n");
sClient = accept( sListen, (sockaddr*)&addrClient, &addrClientLen );
;;;;;if( sClient == WSAEWOULDBLOCK )
{
printf("!!! 非阻塞模式设定 accept调用不正\n");
continue;
}
else if( sClient == INVALID_SOCKET )
{
printf("!!! accept failed: %d\n", WSAGetLastError());
continue;
} //新的连接可以使用,查看待决处理队列
if( nConnNum
for(nLoopi=0; nLoopi
if( g_fd_ArrayC[nLoopi] == 0 )
{//添加新的可用连接
g_fd_ArrayC[nLoopi] = sClient;
break;
}
} ++nConnNum;
printf("-新的客户端信息:[%d] %s:%d\n", sClient, inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port));
}
else
{
printf("-服务器端连接数已满: %d\n", sClient);
send( sClient, noresponseBuff, strlen(noresponseBuff), 0 );
closesocket( sClient );
} }//if( FD_ISSET( sListen, &fdRead) ) }//while(true) printf("-关闭服务器端SOCKET\n");
closesocket( sListen );
WSACleanup(); return 0;
}
////////////////////////////////////////////
//
// TCP Client 非阻塞模式设定
//
////////////////////////////////////////////
#define CONNECT_IP "127.0.0.1"
#define CONNECT_PORT 1207
#define DEFAULT_BUFF_LEN 256int _tmain(int argc, _TCHAR* argv[])
{
WSAData wsData;
SOCKET sServer;
SOCKADDR_IN addrServer;
SOCKADDR_IN addrLocal;
char sendBuff[DEFAULT_BUFF_LEN]={0};
char recvBuff[DEFAULT_BUFF_LEN]={0};
int nError; printf(">>>>>TCP 客户端启动<<<<<<\n");
WSAStartup( MAKEWORD(2,2), &wsData ); printf("-创建客户端用SOCKET\n");
sServer = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( sServer == INVALID_SOCKET )
{
printf("!!! socket failed: %d\n", WSAGetLastError());
WSACleanup();
return -1;
} addrServer.sin_family = AF_INET;
addrServer.sin_addr.S_un.S_addr = inet_addr( CONNECT_IP );
addrServer.sin_port = htons(CONNECT_PORT);
printf("-设定服务器地址信息: %s:%d\n",inet_ntoa(addrServer.sin_addr), ntohs(addrServer.sin_port));
//设定本地用地址和端口
addrLocal.sin_family = AF_INET;
addrLocal.sin_addr.S_un.S_addr = inet_addr( CONNECT_IP );
addrLocal.sin_port = htons( 2701 ); printf("-绑定本地用地址和端口: %s:%d\n", inet_ntoa(addrLocal.sin_addr), ntohs(addrLocal.sin_port));
nError = bind( sServer, (const sockaddr*)&addrLocal, sizeof(addrLocal) );
if( nError == SOCKET_ERROR )
{
printf("!!! bind failed: %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
printf("-连接指定服务器\n");
nError = connect( sServer, (const sockaddr*)&addrServer, sizeof(addrServer) );
if( nError == SOCKET_ERROR )
{
printf("!!! connect failed: %d\n", WSAGetLastError());
closesocket( sServer );
WSACleanup();
return -1;
} ///////////////////////////////////
// 客户端 SOCKET为非阻塞模式
//
///////////////////////////////////
DWORD nMode = 1;
nError = ioctlsocket( sServer, FIONBIO, &nMode );
if( nError == SOCKET_ERROR )
{
printf("!!! ioctlsocket failed: %d\n", WSAGetLastError());
closesocket( sServer );
WSACleanup();
return -1;
}
printf("-SOCKET模式设定: %s\n", (nMode==0?"阻塞模式设定":"非阻塞模式设定"));
printf("-开始准备送信受信\n");
int nInputLen = 0;
int nIndex = 0;
int nLeft = 0; fd_set fdRead;
fd_set fdWrite;
timeval tv={10,0};
while(true)
{ FD_ZERO( &fdRead );
FD_ZERO( &fdWrite );
FD_SET( sServer, &fdRead );
FD_SET( sServer, &fdWrite ); nError = select( 0, &fdRead, &fdWrite, NULL, &tv );
;;;;;if( nError == 0 )
{
printf("!!! select time out\n");
continue;
}
else if( nError < 0 )
{
printf("!!! select failed: %d\n", WSAGetLastError());
break;
}
//发现SOCKET可读/可写
if( FD_ISSET( sServer, &fdRead) )
{
memset( recvBuff, 0, sizeof(recvBuff) );
nError = recv( sServer, recvBuff, sizeof(recvBuff)-1, 0 );
;;;;;if( nError == SOCKET_ERROR )
{
printf("!!! recv failed: %d\n", WSAGetLastError());
break;
}
else if( nError == 0 )
{
printf("-Server Has Closed.\n");
break;
}
recvBuff[nError] = '\0';
printf("-Received: %s\n\n", recvBuff);
} if( FD_ISSET(sServer, &fdWrite) )
{
printf("Input Message You Want to Send( Quit ):\n");
fflush( stdin );
memset( sendBuff, 0, sizeof(sendBuff) ); fgets( sendBuff, sizeof(sendBuff)-1, stdin );
nInputLen = strlen( sendBuff );
sendBuff[nInputLen-1] = '\0';//去掉回车符
--nInputLen;
nIndex = 0;
nLeft = nInputLen; if(strcmp(sendBuff, "Quit")==0)
{
break;
} //将输入的数据发送过去
while( nLeft > 0)
{
nError = send( sServer, &sendBuff[nIndex], nLeft, 0 );
;;;;if( nError == SOCKET_ERROR )
{
printf("!!! send failed: %d\n",WSAGetLastError());
closesocket( sServer );
WSACleanup();
return -1;
}
else if( nError == 0 )
{
printf("-Send OK.\n");
break;
}
nLeft -= nError;
nIndex += nError;
} printf("-Has send: %s\n",sendBuff);
} }//while(true)
printf("-关闭SOCKET\n");
closesocket(sServer);
WSACleanup(); return 0;
}
socket 非阻塞程序怎么写?
SOCKET编程中如何实现非阻塞式运行
如何将CSocket设置为非阻塞模式(VC)
如何在单机Linux上运行Socket TCP和UDP Server/Client的通信程序
阻塞模式的概念
socket通信编程
无法执行SOCKET的TCP
socket 和ip, tcp之间是什么关系?
请问socket和TCP协议的关系?
java非阻塞编程的一个问题
TCP/IP有哪些通信类型
TCP标志:S是什么意思呢?
编写TCP协议,用windows socket编程可以吗?
tornado打开时出错 svctcp_.c -tcp socket creation problem
交换机的术语,什么是Non-Blocking非阻塞交换结构
非阻塞java在注册事件时的一个问题
如何将CSocket设置为阻塞模式(VC)
基于SNMP++的阻塞模式收发应用研究
非预置模式
添加集线器用来连接网络,会使LAN通信量出现阻塞吗??为什么?
LABVIEW里面怎么进行TCP/IP通信?
那同一个BSS内两个非AP站点通信时需不需要经过AP,不管是DCF和PCF模式下
我在BCB(C++ builder)中通信程序报错ESockError with message '10038:Socket operation on non-socket
谁能提供SOCKET 处理TCP服务端监听详细处理过程?