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

来源:互联网 发布:mg动画简易软件 编辑:程序博客网 时间:2024/06/03 11:18

别的不多说了,看代码吧。

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

原创粉丝点击