您的位置:首页 > 理论基础 > 计算机网络

windows下的网络编程——Select模型实例,一款ECHO服务的实现代码

2011-05-24 13:52 841 查看
别的不多说了,看代码吧。

ECHO服务器端:

view plaincopy to clipboardprint?
01.#include <winsock2.h>
02.#include <stdio.h>
03.#include <stdlib.h>
04.
05.
06.#define DEFAULT_PORT 5566
07.#define BUFFER_SIZE 4096
08.#define DEFAULT_ADDR_LEN 128
09.#define MAX_CLIENT (FD_SETSIZE -1)
10.int nPort = DEFAULT_PORT;
11.char szAddr[DEFAULT_ADDR_LEN];
12.char szBuffer[BUFFER_SIZE];
13.BOOL bInterface = FALSE;
14.BOOL bEchoBack = FALSE;
15.
16.void usage(void);
17.void checkArgv(int argc, char **argv);
18.BOOL insertSocket(SOCKET *pClient, SOCKET s);
19.
20.int main(int argc, char *argv[])
21.{
22. WSAData wsaData;
23. WORD wVersion = MAKEWORD(2,2);
24. SOCKET s, sClient;
25. SOCKADDR_IN sa, saRemote;
26. int nRet, nLen, i, nLeft, idx, nRecvLen;
27. SOCKET arrClientSocket[MAX_CLIENT] = {INVALID_SOCKET};
28.
29. checkArgv(argc, argv);
30. nRet = WSAStartup(wVersion, &wsaData);
31.
32. if (SOCKET_ERROR == nRet)
33. {
34. printf("/nWindows socket startup error:%d/n", WSAGetLastError());
35. return 1;
36. }
37.
38. printf("Socket initalization...../n");
39.
40. s = socket(AF_INET, SOCK_STREAM, 0);
41. if (INVALID_SOCKET == s)
42. {
43. printf("/nScoket was created error:%d/n", WSAGetLastError());
44. return 1;
45. }
46.
47. printf("socket was created/n");
48.
49. nLen = sizeof(SOCKADDR_IN);
50. memset(&sa, 0, nLen);
51. sa.sin_family = AF_INET;
52. sa.sin_port = htons(nPort);
53.
54. if (bInterface)
55. {
56. sa.sin_addr.s_addr = inet_addr(szAddr);
57. }
58. else
59. {
60. sa.sin_addr.s_addr = htonl(INADDR_ANY);
61. }
62.
63. nRet = bind(s, (LPSOCKADDR)&sa, nLen);
64. if (SOCKET_ERROR == nRet)
65. {
66. printf("Socket bind error:%d/n", WSAGetLastError());
67. return 1;
68. }
69.
70. printf("bind was successed/n");
71.
72. nRet = listen(s, 8);
73. if (SOCKET_ERROR == nRet)
74. {
75. printf("Socket listen error:%d/n", WSAGetLastError());
76. return 1;
77. }
78.
79. printf("listen was successed/n");
80.
81. fd_set fdRead;
82. for(i = 0;i < MAX_CLIENT; i++)
83. {
84. arrClientSocket[i] = INVALID_SOCKET;
85. }
86.
87. for(;;)
88. {
89. //初始化队列,将所有套接字加入。
90. FD_ZERO(&fdRead);
91. FD_SET(s, &fdRead);
92. for(i = 0; i < MAX_CLIENT; i++)
93. {
94. if (INVALID_SOCKET != arrClientSocket[i])
95. {
96. FD_SET(arrClientSocket[i], &fdRead);
97. }
98. }
99.
100. nRet = select(0, &fdRead, NULL, NULL, NULL);
101. if (SOCKET_ERROR == nRet)
102. {
103. printf("/nSelect() error:%d/n", WSAGetLastError());
104. break;
105. }
106.
107. if (nRet > 0)
108. {
109. //说明有新SOCKET连接到服务器
110. if(FD_ISSET(s, &fdRead))
111. {
112. sClient = accept(s, (LPSOCKADDR)&saRemote, &nLen);
113. insertSocket(arrClientSocket, sClient);
114. printf("Sokcet:%d, was accept()/n", sClient);
115. continue;
116. }
117. for(i = 0; i < MAX_CLIENT; i++)
118. {
119. if (FD_ISSET(arrClientSocket[i], &fdRead))
120. {
121. memset(szBuffer, 0, BUFFER_SIZE);
122. nRet = recv(arrClientSocket[i], szBuffer, BUFFER_SIZE, 0);
123. if (nRet <= 0)
124. {
125. closesocket(arrClientSocket[i]);
126. arrClientSocket[i] = INVALID_SOCKET;
127. continue;
128. }
129.
130. nRecvLen = nRet;
131. printf("Socket:%d, %d, send data:%s/n", arrClientSocket[i], nRet, szBuffer);
132.
133.
134. if (!bEchoBack)
135. {
136. nRet = getpeername(arrClientSocket[i], (LPSOCKADDR)&saRemote, &nLen);
137. if (SOCKET_ERROR == nRet)
138. {
139. printf("/ngetpeername() error:%d/n", WSAGetLastError());
140. continue;
141. }
142. nLeft = nRecvLen;
143. idx = 0;
144. while (nLeft > 0)
145. {
146. nRet = send(arrClientSocket[i], &szBuffer[idx], nLeft, 0);
147. if (0 == nRet)
148. break;
149. else if (SOCKET_ERROR == nRet)
150. {
151. printf("Send() failed:%d/n", WSAGetLastError());
152. break;
153. }
154. nLeft -= nRet;
155. idx += nRet;
156. }
157. }
158. }
159. }
160. }
161. }
162. closesocket(s);
163. WSACleanup();
164. return 0;
165.}
166.
167.void usage(void)
168.{
169. printf("usage: selectecho.exe [-p:5566] [-i:127.0.0.1] [-o]/n/n");
170. printf("/t-p:监听的端口号, 在1024到65535之间/n");
171. printf("/t-i:监听的服务器地址/n");
172. printf("/t-o:是否将数据发回客户端/n/n");
173. ExitProcess(1);
174.}
175.
176.void checkArgv(int argc, char **argv)
177.{
178. int i;
179. for(i = 1; i < argc; i++)
180. {
181. if(('/' == argv[i][0]) || ('-' == argv[i][1]))
182. {
183. switch(tolower(argv[i][1]))
184. {
185. case 'p':
186. nPort = atoi(&argv[i][3]);
187. break;
188. case 'i':
189. memset(szAddr, 0, DEFAULT_ADDR_LEN);
190. strcpy(szAddr, &argv[i][3]);
191. bInterface = TRUE;
192. break;
193. case 'o':
194. bEchoBack = TRUE;
195. break;
196. default:
197. usage();
198. break;
199. }
200. }
201. }
202.}
203.
204.BOOL insertSocket(SOCKET *pClient, SOCKET s)
205.{
206. int i;
207. BOOL bResult = FALSE;
208. for(i = 0; i < MAX_CLIENT; i++)
209. {
210. if (INVALID_SOCKET == pClient[i])
211. {
212. pClient[i] = s;
213. bResult = TRUE;
214. break;
215. }
216. }
217. return bResult;
218.}
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>

#define DEFAULT_PORT 5566
#define BUFFER_SIZE 4096
#define DEFAULT_ADDR_LEN 128
#define MAX_CLIENT (FD_SETSIZE -1)
int nPort = DEFAULT_PORT;
char szAddr[DEFAULT_ADDR_LEN];
char szBuffer[BUFFER_SIZE];
BOOL bInterface = FALSE;
BOOL bEchoBack = FALSE;

void usage(void);
void checkArgv(int argc, char **argv);
BOOL insertSocket(SOCKET *pClient, SOCKET s);

int main(int argc, char *argv[])
{
WSAData wsaData;
WORD wVersion = MAKEWORD(2,2);
SOCKET s, sClient;
SOCKADDR_IN sa, saRemote;
int nRet, nLen, i, nLeft, idx, nRecvLen;
SOCKET arrClientSocket[MAX_CLIENT] = {INVALID_SOCKET};

checkArgv(argc, argv);
nRet = WSAStartup(wVersion, &wsaData);

if (SOCKET_ERROR == nRet)
{
printf("/nWindows socket startup error:%d/n", WSAGetLastError());
return 1;
}

printf("Socket initalization...../n");

s = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == s)
{
printf("/nScoket was created error:%d/n", WSAGetLastError());
return 1;
}

printf("socket was created/n");

nLen = sizeof(SOCKADDR_IN);
memset(&sa, 0, nLen);
sa.sin_family = AF_INET;
sa.sin_port = htons(nPort);

if (bInterface)
{
sa.sin_addr.s_addr = inet_addr(szAddr);
}
else
{
sa.sin_addr.s_addr = htonl(INADDR_ANY);
}

nRet = bind(s, (LPSOCKADDR)&sa, nLen);
if (SOCKET_ERROR == nRet)
{
printf("Socket bind error:%d/n", WSAGetLastError());
return 1;
}

printf("bind was successed/n");

nRet = listen(s, 8);
if (SOCKET_ERROR == nRet)
{
printf("Socket listen error:%d/n", WSAGetLastError());
return 1;
}

printf("listen was successed/n");

fd_set fdRead;
for(i = 0;i < MAX_CLIENT; i++)
{
arrClientSocket[i] = INVALID_SOCKET;
}

for(;;)
{
//初始化队列,将所有套接字加入。
FD_ZERO(&fdRead);
FD_SET(s, &fdRead);
for(i = 0; i < MAX_CLIENT; i++)
{
if (INVALID_SOCKET != arrClientSocket[i])
{
FD_SET(arrClientSocket[i], &fdRead);
}
}

nRet = select(0, &fdRead, NULL, NULL, NULL);
if (SOCKET_ERROR == nRet)
{
printf("/nSelect() error:%d/n", WSAGetLastError());
break;
}

if (nRet > 0)
{
//说明有新SOCKET连接到服务器
if(FD_ISSET(s, &fdRead))
{
sClient = accept(s, (LPSOCKADDR)&saRemote, &nLen);
insertSocket(arrClientSocket, sClient);
printf("Sokcet:%d, was accept()/n", sClient);
continue;
}
for(i = 0; i < MAX_CLIENT; i++)
{
if (FD_ISSET(arrClientSocket[i], &fdRead))
{
memset(szBuffer, 0, BUFFER_SIZE);
nRet = recv(arrClientSocket[i], szBuffer, BUFFER_SIZE, 0);
if (nRet <= 0)
{
closesocket(arrClientSocket[i]);
arrClientSocket[i] = INVALID_SOCKET;
continue;
}

nRecvLen = nRet;
printf("Socket:%d, %d, send data:%s/n", arrClientSocket[i], nRet, szBuffer);


if (!bEchoBack)
{
nRet = getpeername(arrClientSocket[i], (LPSOCKADDR)&saRemote, &nLen);
if (SOCKET_ERROR == nRet)
{
printf("/ngetpeername() error:%d/n", WSAGetLastError());
continue;
}
nLeft = nRecvLen;
idx = 0;
while (nLeft > 0)
{
nRet = send(arrClientSocket[i], &szBuffer[idx], nLeft, 0);
if (0 == nRet)
break;
else if (SOCKET_ERROR == nRet)
{
printf("Send() failed:%d/n", WSAGetLastError());
break;
}
nLeft -= nRet;
idx += nRet;
}
}
}
}
}
}
closesocket(s);
WSACleanup();
return 0;
}

void usage(void)
{
printf("usage: selectecho.exe [-p:5566] [-i:127.0.0.1] [-o]/n/n");
printf("/t-p:监听的端口号, 在1024到65535之间/n");
printf("/t-i:监听的服务器地址/n");
printf("/t-o:是否将数据发回客户端/n/n");
ExitProcess(1);
}

void checkArgv(int argc, char **argv)
{
int i;
for(i = 1; i < argc; i++)
{
if(('/' == argv[i][0]) || ('-' == argv[i][1]))
{
switch(tolower(argv[i][1]))
{
case 'p':
nPort = atoi(&argv[i][3]);
break;
case 'i':
memset(szAddr, 0, DEFAULT_ADDR_LEN);
strcpy(szAddr, &argv[i][3]);
bInterface = TRUE;
break;
case 'o':
bEchoBack = TRUE;
break;
default:
usage();
break;
}
}
}
}

BOOL insertSocket(SOCKET *pClient, SOCKET s)
{
int i;
BOOL bResult = FALSE;
for(i = 0; i < MAX_CLIENT; i++)
{
if (INVALID_SOCKET == pClient[i])
{
pClient[i] = s;
bResult = TRUE;
break;
}
}
return bResult;
}

测试用客户端,目前地址写在了程序中,用户可以自行修改。

view plaincopy to clipboardprint?
01.#include <stdio.h>
02.#include <stdlib.h>
03.#include <winsock2.h>
04.
05.#define SERVER_PORT 5566
06.#define BUFFER_SIZE 4096
07.#define MAX_ADDR_LEN 128
08.
09.int nPort = SERVER_PORT;
10.char szBuffer[BUFFER_SIZE];
11.char szAddr[MAX_ADDR_LEN];
12.
13.void usage(void);
14.void checkArgv(int argc, char **argv);
15.
16.int main(int argc, char *argv[])
17.{
18. int nRet, nLen, nAddrLen, i;
19. SOCKET s;
20. SOCKADDR_IN sa;
21.
22. WSAData wsaData;
23. WORD wVersion = MAKEWORD(2,2);
24.
25. checkArgv(argc, argv);
26.
27. nRet = WSAStartup(wVersion, &wsaData);
28. if (SOCKET_ERROR == nRet)
29. {
30. printf("Socket init error/n");
31. return 1;
32. }
33.
34. s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
35. if (INVALID_SOCKET == s)
36. {
37. printf("Socket was created failse:%d/n", WSAGetLastError());
38. closesocket(s);
39. WSACleanup();
40. return 1;
41. }
42.
43. nAddrLen = sizeof(SOCKADDR_IN);
44. memset(&sa, 0, nAddrLen);
45. sa.sin_family = AF_INET;
46. sa.sin_port = htons(nPort);
47. sa.sin_addr.s_addr = inet_addr("127.0.0.1");
48.
49. nRet = connect(s, (LPSOCKADDR)&sa, nAddrLen);
50. if (SOCKET_ERROR == nRet)
51. {
52. printf("socket connect() failse:%d/n", WSAGetLastError());
53. closesocket(s);
54. WSACleanup();
55. return 1;
56. }
57.
58. for(;;)
59. {
60. printf("/nSend Message to ECHO:");
61. memset(szBuffer, 0, BUFFER_SIZE);
62. nRet = scanf("%s", szBuffer);
63. if (BUFFER_SIZE < nRet)
64. {
65. szBuffer[BUFFER_SIZE-1] = '/0';
66. }
67. if (0 == strcmp("quit",szBuffer)) break; //输入QUIT退出当前客户端
68. nRet = send(s, szBuffer, strlen(szBuffer), 0);
69. if (SOCKET_ERROR == nRet)
70. {
71. printf("Socket send() failse:%d/n", WSAGetLastError());
72. break;
73. }
74. memset(szBuffer, 0, BUFFER_SIZE);
75. nRet = recv(s, szBuffer, BUFFER_SIZE, 0);
76. printf("Server ECHO back:%s/n", szBuffer);
77. }
78.
79.
80. closesocket(s);
81. WSACleanup();
82. return 0;
83.}
84.
85.void usage(void)
86.{
87. printf("usage: selectecho.exe -i:127.0.0.1 [-p:5566]/n");
88. printf("/t-i:服务器地址/n");
89. printf("/t-p:服务器端口号, 在1024到65535之间/n");
90. ExitProcess(1);
91.}
92.
93.void checkArgv(int argc, char **argv)
94.{
95. int i;
96. memset(szAddr, 0, MAX_ADDR_LEN);
97. for(i = 1; i < argc; i++)
98. {
99. if(('/' == argv[i][0]) || ('-' == argv[i][1]))
100. {
101. switch(tolower(argv[i][1]))
102. {
103. case 'p':
104. nPort = atoi(&argv[i][3]);
105. break;
106. case 'i':
107. strcpy(szAddr, &argv[i][3]);
108. printf("%s", argv[i][3]);
109. break;
110. default:
111. usage();
112. break;
113. }
114. }
115. }
116.}
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>

#define SERVER_PORT 5566
#define BUFFER_SIZE 4096
#define MAX_ADDR_LEN 128

int nPort = SERVER_PORT;
char szBuffer[BUFFER_SIZE];
char szAddr[MAX_ADDR_LEN];

void usage(void);
void checkArgv(int argc, char **argv);

int main(int argc, char *argv[])
{
int nRet, nLen, nAddrLen, i;
SOCKET s;
SOCKADDR_IN sa;

WSAData wsaData;
WORD wVersion = MAKEWORD(2,2);

checkArgv(argc, argv);

nRet = WSAStartup(wVersion, &wsaData);
if (SOCKET_ERROR == nRet)
{
printf("Socket init error/n");
return 1;
}

s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == s)
{
printf("Socket was created failse:%d/n", WSAGetLastError());
closesocket(s);
WSACleanup();
return 1;
}

nAddrLen = sizeof(SOCKADDR_IN);
memset(&sa, 0, nAddrLen);
sa.sin_family = AF_INET;
sa.sin_port = htons(nPort);
sa.sin_addr.s_addr = inet_addr("127.0.0.1");

nRet = connect(s, (LPSOCKADDR)&sa, nAddrLen);
if (SOCKET_ERROR == nRet)
{
printf("socket connect() failse:%d/n", WSAGetLastError());
closesocket(s);
WSACleanup();
return 1;
}

for(;;)
{
printf("/nSend Message to ECHO:");
memset(szBuffer, 0, BUFFER_SIZE);
nRet = scanf("%s", szBuffer);
if (BUFFER_SIZE < nRet)
{
szBuffer[BUFFER_SIZE-1] = '/0';
}
if (0 == strcmp("quit",szBuffer)) break; //输入QUIT退出当前客户端
nRet = send(s, szBuffer, strlen(szBuffer), 0);
if (SOCKET_ERROR == nRet)
{
printf("Socket send() failse:%d/n", WSAGetLastError());
break;
}
memset(szBuffer, 0, BUFFER_SIZE);
nRet = recv(s, szBuffer, BUFFER_SIZE, 0);
printf("Server ECHO back:%s/n", szBuffer);
}


closesocket(s);
WSACleanup();
return 0;
}

void usage(void)
{
printf("usage: selectecho.exe -i:127.0.0.1 [-p:5566]/n");
printf("/t-i:服务器地址/n");
printf("/t-p:服务器端口号, 在1024到65535之间/n");
ExitProcess(1);
}

void checkArgv(int argc, char **argv)
{
int i;
memset(szAddr, 0, MAX_ADDR_LEN);
for(i = 1; i < argc; i++)
{
if(('/' == argv[i][0]) || ('-' == argv[i][1]))
{
switch(tolower(argv[i][1]))
{
case 'p':
nPort = atoi(&argv[i][3]);
break;
case 'i':
strcpy(szAddr, &argv[i][3]);
printf("%s", argv[i][3]);
break;
default:
usage();
break;
}
}
}
}

Windows下的编译命令为:

cl -o 服务器程序名称.exe 源文件名称.cpp WS2_32.lib

客户端编译同上,只是修改文件名即可。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/dxl2005/archive/2010/09/23/5902346.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: