Windows socket I/O模型 之 select(1)
2014-04-19 15:06
260 查看
参考1:http://blog.csdn.net/zjsiva/article/details/5895087
我喜欢直接上代码,请看,在上述代码增加了一些内容。
比如服务器自动回复客户机请求。
// 服务器
[cpp]
view plaincopyprint?
// Select_Server.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <WINSOCK2.H>
#pragma comment(lib,"ws2_32.lib")
#define STR_SERVER_IP "127.0.0.1"
#define INT_SERVER_PORT 6002
#define INT_DATABUFFER_SIZE 256
int _tmain(int argc, _TCHAR* argv[])
{
WORD dwVersion = MAKEWORD(2,2);
WSAData wsaData;
WSAStartup(WINSOCK_VERSION,&wsaData);
SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == sockServer) {
printf("Failed to create socket!\r\n");
WSACleanup();
return -1;
}
sockaddr_in addrServer;
memset(&addrServer,0,sizeof(sockaddr_in));
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(INT_SERVER_PORT);
addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
//addrServer.sin_addr.s_addr = htonl(INADDR_ANY);
int iResult;
bool bReuseAddr = true;
iResult=setsockopt(sockServer,SOL_SOCKET,SO_REUSEADDR,(char *)&bReuseAddr,sizeof(bReuseAddr));
if(SOCKET_ERROR == iResult) {
printf("Failed to set resueaddr socket!\r\n");
WSACleanup();
return -1;
}
/*
unsigned long cmd = 1;
iResult= ioctlsocket(sockServer,FIONBIO,&cmd); */
iResult = bind(sockServer,(sockaddr *)&addrServer,sizeof(addrServer));
if (SOCKET_ERROR == iResult) {
printf("Failed to bind address!\r\n");
WSACleanup();
return -1;
}
if (0 != listen(sockServer,5)) {
printf("Failed to listen client!\r\n");
WSACleanup();
return -1;
}
UINT i = 0;
SOCKET sockAccept;
sockaddr_in addrAccept;
int iAcceptLen = sizeof(addrAccept);
char szDataBuff[INT_DATABUFFER_SIZE];
int iRecvSize;
sockaddr_in addrTemp;
int iTempLen;
fd_set fd;
FD_ZERO(&fd);
FD_SET(sockServer, &fd);
/*
timeval tm;
tm.tv_sec = 0;
tm.tv_usec = 1000;
*/
printf("Start server...\r\n");
while(1) {
fd_set fdOld = fd;
iResult = select(0, &fdOld, NULL, NULL, /*&tm*/NULL);
if (0 <= iResult) {
for(i = 0; i < fd.fd_count; i++) {
if (FD_ISSET(fd.fd_array[i], &fdOld)) {
//如果socket是服务器,则接收连接
if (fd.fd_array[i] == sockServer) {
memset(&addrAccept,0,sizeof(addrTemp));
sockAccept = accept(sockServer, (sockaddr *)&addrAccept, &iAcceptLen);
if (INVALID_SOCKET != sockAccept) {
FD_SET(sockAccept, &fd);
//FD_SET(sockAccept,&fdOld);
printf("%s:%d has connected server!\r\n", inet_ntoa(addrAccept.sin_addr),
ntohs(addrAccept.sin_port));
}
} else { //非服务器,接收数据(因为fd是读数据集)
memset(szDataBuff, 0, INT_DATABUFFER_SIZE);
iRecvSize = recv(fd.fd_array[i], szDataBuff, INT_DATABUFFER_SIZE, 0);
memset(&addrTemp, 0, sizeof(addrTemp));
iTempLen = sizeof(addrTemp);
getpeername(fd.fd_array[i], (sockaddr *)&addrTemp, &iTempLen);
// an error occurs
if (SOCKET_ERROR == iRecvSize) {
closesocket(fd.fd_array[i]);
FD_CLR(fd.fd_array[i], &fd);
i--;
printf("Failed to recv data ,%s:%d errorcode:%d.\r\n",
inet_ntoa(addrTemp.sin_addr),ntohs(addrTemp.sin_port),WSAGetLastError());
continue;
}
// 客户socket关闭
if (0 == iRecvSize) {
printf("%s:%d has closed!\r\n",inet_ntoa(addrTemp.sin_addr),
ntohs(addrTemp.sin_port));
closesocket(fd.fd_array[i]);
FD_CLR(fd.fd_array[i],&fd);
i--;
}
// no error occurs, returns the number of bytes received
if (0 < iRecvSize) {
printf("recv %s:%d data:%s\r\n", inet_ntoa(addrTemp.sin_addr),
ntohs(addrTemp.sin_port),szDataBuff);
char szEcho[256] = {0};
sprintf(szEcho, "Server has got: %s.", szDataBuff);
send(fd.fd_array[i], szEcho, strlen(szEcho), 0);
}
}
}
}
} else if (SOCKET_ERROR == iResult) {
int iErr = WSAGetLastError();
//WSACleanup();
printf("Faild to select sockt in server!(Error: %d)\r\n", iErr);
Sleep(100);
}
}
WSACleanup();
return 0;
}
// 客户机
[cpp]
view plaincopyprint?
// Select_Client.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <WINSOCK2.H>
#pragma comment(lib,"ws2_32.lib")
#define INT_SERVER_PORT 6002
#define STR_SERVER_IP "127.0.0.1"
#define INT_DATABUFFER_SIZE 256
#define STR_EXIT "exit"
#define STR_RECV "recv"
void main(void)
{
WSAData wsaData;
WSAStartup(WINSOCK_VERSION,&wsaData);
SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);
if (INVALID_SOCKET == sockClient) {
printf("Failed to create client!\r\n");
WSACleanup();
}
sockaddr_in addrClient;
addrClient.sin_addr.S_un.S_addr = inet_addr(STR_SERVER_IP);
addrClient.sin_family = AF_INET;
addrClient.sin_port = htons(INT_SERVER_PORT);
int iResult;
iResult = connect(sockClient,(sockaddr *)&addrClient,sizeof(sockaddr_in));
if (SOCKET_ERROR == iResult) {
printf("Failed to connect server!\r\n");
WSACleanup();
return;
}
if (0 != iResult) {
int iErrorCode;
iErrorCode = WSAGetLastError();
printf("Failed to connect server,error:%d.\r\n",iErrorCode);
WSACleanup();
return;
}
char szDataBuffer[INT_DATABUFFER_SIZE];
while(1) {
memset(szDataBuffer,0,INT_DATABUFFER_SIZE);
scanf("%s",szDataBuffer);
if (0 == strcmp(szDataBuffer, STR_EXIT)) {
printf("The client has stopped!\r\n");
break;
} else if( 0 == strcmp(szDataBuffer, STR_RECV)) {
int ret = recv(sockClient, szDataBuffer, 256, 0);
printf("Recv server echo: %s\r\n", szDataBuffer);
} else {
if (1 > send(sockClient, szDataBuffer, strlen(szDataBuffer),0)) {
printf("Failed to send data!\r\n");
}
}
Sleep(100);
}
closesocket(sockClient);
WSACleanup();
}
这里需要注意的就是 fd_set, FD_ZERO,FD_SET,FD_ISSET这几个宏的用法。
我喜欢直接上代码,请看,在上述代码增加了一些内容。
比如服务器自动回复客户机请求。
// 服务器
[cpp]
view plaincopyprint?
// Select_Server.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <WINSOCK2.H>
#pragma comment(lib,"ws2_32.lib")
#define STR_SERVER_IP "127.0.0.1"
#define INT_SERVER_PORT 6002
#define INT_DATABUFFER_SIZE 256
int _tmain(int argc, _TCHAR* argv[])
{
WORD dwVersion = MAKEWORD(2,2);
WSAData wsaData;
WSAStartup(WINSOCK_VERSION,&wsaData);
SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == sockServer) {
printf("Failed to create socket!\r\n");
WSACleanup();
return -1;
}
sockaddr_in addrServer;
memset(&addrServer,0,sizeof(sockaddr_in));
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(INT_SERVER_PORT);
addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
//addrServer.sin_addr.s_addr = htonl(INADDR_ANY);
int iResult;
bool bReuseAddr = true;
iResult=setsockopt(sockServer,SOL_SOCKET,SO_REUSEADDR,(char *)&bReuseAddr,sizeof(bReuseAddr));
if(SOCKET_ERROR == iResult) {
printf("Failed to set resueaddr socket!\r\n");
WSACleanup();
return -1;
}
/*
unsigned long cmd = 1;
iResult= ioctlsocket(sockServer,FIONBIO,&cmd); */
iResult = bind(sockServer,(sockaddr *)&addrServer,sizeof(addrServer));
if (SOCKET_ERROR == iResult) {
printf("Failed to bind address!\r\n");
WSACleanup();
return -1;
}
if (0 != listen(sockServer,5)) {
printf("Failed to listen client!\r\n");
WSACleanup();
return -1;
}
UINT i = 0;
SOCKET sockAccept;
sockaddr_in addrAccept;
int iAcceptLen = sizeof(addrAccept);
char szDataBuff[INT_DATABUFFER_SIZE];
int iRecvSize;
sockaddr_in addrTemp;
int iTempLen;
fd_set fd;
FD_ZERO(&fd);
FD_SET(sockServer, &fd);
/*
timeval tm;
tm.tv_sec = 0;
tm.tv_usec = 1000;
*/
printf("Start server...\r\n");
while(1) {
fd_set fdOld = fd;
iResult = select(0, &fdOld, NULL, NULL, /*&tm*/NULL);
if (0 <= iResult) {
for(i = 0; i < fd.fd_count; i++) {
if (FD_ISSET(fd.fd_array[i], &fdOld)) {
//如果socket是服务器,则接收连接
if (fd.fd_array[i] == sockServer) {
memset(&addrAccept,0,sizeof(addrTemp));
sockAccept = accept(sockServer, (sockaddr *)&addrAccept, &iAcceptLen);
if (INVALID_SOCKET != sockAccept) {
FD_SET(sockAccept, &fd);
//FD_SET(sockAccept,&fdOld);
printf("%s:%d has connected server!\r\n", inet_ntoa(addrAccept.sin_addr),
ntohs(addrAccept.sin_port));
}
} else { //非服务器,接收数据(因为fd是读数据集)
memset(szDataBuff, 0, INT_DATABUFFER_SIZE);
iRecvSize = recv(fd.fd_array[i], szDataBuff, INT_DATABUFFER_SIZE, 0);
memset(&addrTemp, 0, sizeof(addrTemp));
iTempLen = sizeof(addrTemp);
getpeername(fd.fd_array[i], (sockaddr *)&addrTemp, &iTempLen);
// an error occurs
if (SOCKET_ERROR == iRecvSize) {
closesocket(fd.fd_array[i]);
FD_CLR(fd.fd_array[i], &fd);
i--;
printf("Failed to recv data ,%s:%d errorcode:%d.\r\n",
inet_ntoa(addrTemp.sin_addr),ntohs(addrTemp.sin_port),WSAGetLastError());
continue;
}
// 客户socket关闭
if (0 == iRecvSize) {
printf("%s:%d has closed!\r\n",inet_ntoa(addrTemp.sin_addr),
ntohs(addrTemp.sin_port));
closesocket(fd.fd_array[i]);
FD_CLR(fd.fd_array[i],&fd);
i--;
}
// no error occurs, returns the number of bytes received
if (0 < iRecvSize) {
printf("recv %s:%d data:%s\r\n", inet_ntoa(addrTemp.sin_addr),
ntohs(addrTemp.sin_port),szDataBuff);
char szEcho[256] = {0};
sprintf(szEcho, "Server has got: %s.", szDataBuff);
send(fd.fd_array[i], szEcho, strlen(szEcho), 0);
}
}
}
}
} else if (SOCKET_ERROR == iResult) {
int iErr = WSAGetLastError();
//WSACleanup();
printf("Faild to select sockt in server!(Error: %d)\r\n", iErr);
Sleep(100);
}
}
WSACleanup();
return 0;
}
// 客户机
[cpp]
view plaincopyprint?
// Select_Client.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <WINSOCK2.H>
#pragma comment(lib,"ws2_32.lib")
#define INT_SERVER_PORT 6002
#define STR_SERVER_IP "127.0.0.1"
#define INT_DATABUFFER_SIZE 256
#define STR_EXIT "exit"
#define STR_RECV "recv"
void main(void)
{
WSAData wsaData;
WSAStartup(WINSOCK_VERSION,&wsaData);
SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);
if (INVALID_SOCKET == sockClient) {
printf("Failed to create client!\r\n");
WSACleanup();
}
sockaddr_in addrClient;
addrClient.sin_addr.S_un.S_addr = inet_addr(STR_SERVER_IP);
addrClient.sin_family = AF_INET;
addrClient.sin_port = htons(INT_SERVER_PORT);
int iResult;
iResult = connect(sockClient,(sockaddr *)&addrClient,sizeof(sockaddr_in));
if (SOCKET_ERROR == iResult) {
printf("Failed to connect server!\r\n");
WSACleanup();
return;
}
if (0 != iResult) {
int iErrorCode;
iErrorCode = WSAGetLastError();
printf("Failed to connect server,error:%d.\r\n",iErrorCode);
WSACleanup();
return;
}
char szDataBuffer[INT_DATABUFFER_SIZE];
while(1) {
memset(szDataBuffer,0,INT_DATABUFFER_SIZE);
scanf("%s",szDataBuffer);
if (0 == strcmp(szDataBuffer, STR_EXIT)) {
printf("The client has stopped!\r\n");
break;
} else if( 0 == strcmp(szDataBuffer, STR_RECV)) {
int ret = recv(sockClient, szDataBuffer, 256, 0);
printf("Recv server echo: %s\r\n", szDataBuffer);
} else {
if (1 > send(sockClient, szDataBuffer, strlen(szDataBuffer),0)) {
printf("Failed to send data!\r\n");
}
}
Sleep(100);
}
closesocket(sockClient);
WSACleanup();
}
这里需要注意的就是 fd_set, FD_ZERO,FD_SET,FD_ISSET这几个宏的用法。
相关文章推荐
- windows socket----select模型
- Windows socket之Select模型开发
- Windows socket之Select模型开发
- Windows socket之WSAEventSelect模型
- Windows Socket五种I/O模型(一)——选择模型(Select)
- Windows socket I/O模型 之 select(2)
- vc++ windows socket I/O模型 WSAeventSelect 模型例子
- windows socket编程select模型使用
- Windows Socket五种I/O模型(一)——选择模型(Select)
- Windows socket I/O模型 之 select(2)
- Windows socket之Select模型开发
- Windows Socket五种I/O模型——select模型
- Windows Socket I/O模型之 Select模式
- Windows socket I/O模型 之 select(2)
- windows Socket编程之select网络模型
- Windows Socket I/O模型之 WSAAsyncSelect模式
- windows socket----select模型
- Windows socket之WSAEventSelect模型
- Windows socket select模型
- Windows Socket五种I/O模型——select模型