TCP Server/Client, Select

来源:互联网 发布:如何判断病态矩阵 编辑:程序博客网 时间:2024/05/01 07:24
     以前都是采用ACE的编写网络应用,最近由于工作需要,需要直接只用socket接口编写CS的代码,重新学习这方面的知识,给出自己所用到的3个简单例子,都是拷贝别人的程序。如果你能完全理解这3个例子,估计socket编程就已经基本入门了。

      建议:1) 多多查查所用到的网络接口; 2) 最好有一本书,如UNIX环境高级编程,UNIX网络编程,可查询;3) 可以直接使用书上的例子更好。

 

      TCP Client代码:

[cpp] view plain copy
  1. #include   <sys/stat.h>     
  2. #include   <sys/types.h>     
  3. #include   <sys/socket.h>     
  4. #include   <stdio.h>     
  5. #include   <malloc.h>     
  6. #include   <netdb.h>     
  7. #include   <fcntl.h>  
  8. #include   <unistd.h>  
  9. #include   <netinet/in.h>  
  10. #include   <arpa/inet.h>  
  11. #define    RES_LENGTH  10240 //接受字符的最大长度  
  12. int     connect_socket(char * server,int serverPort);  
  13. int     send_msg(int sockfd,char * sendBuff);  
  14. char *  recv_msg(int sockfd);  
  15. int     close_socket(int sockfd);  
  16. int main(int argc, char ** argv)  
  17. {  
  18.     int   sockfd=0;  
  19.     char  sendMsg[30]="abc.org/r/n/r";  
  20.     char* res;  
  21.     int   port = 4242;  
  22.     char  ip[128] = {0};  
  23.     strncpy(ip, "127.0.0.1", 128);  
  24.     if(argc > 2)  
  25.     {  
  26.         strncpy(ip, argv[1], 128);  
  27.         port = atoi(argv[2]);  
  28.         printf("Input IP: %s, port : %d/n", ip, port);  
  29.     }  
  30.     else if(argc > 1)  
  31.     {     
  32.         port = atoi(argv[1]);  
  33.         printf("Input port : %d/n", port);  
  34.     }  
  35.     sockfd=connect_socket(ip, port);  
  36.       
  37.     send_msg(sockfd,sendMsg);  
  38.     /* res=recv_msg(sockfd); */  
  39.       
  40.     printf("return from recv function/n");  
  41.     printf(res);  
  42.     free(res);  
  43.     close_socket(sockfd);  
  44.     return 0;  
  45. }  
  46. /************************************************************ 
  47.  * 连接SOCKET服务器,如果出错返回-1,否则返回socket处理代码 
  48.  * server:服务器地址(域名或者IP),serverport:端口 
  49.  * ********************************************************/  
  50. int    connect_socket(char * server,int serverPort){  
  51.     int    sockfd=0;  
  52.     struct    sockaddr_in    addr;  
  53.     struct    hostent        * phost;  
  54.     //向系统注册,通知系统建立一个通信端口  
  55.     //AF_INET表示使用IPv4协议  
  56.     //SOCK_STREAM表示使用TCP协议  
  57.     if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){  
  58.         herror("Init socket error!");  
  59.         return -1;  
  60.     }  
  61.     bzero(&addr,sizeof(addr));  
  62.     addr.sin_family = AF_INET;  
  63.     addr.sin_port = htons(serverPort);  
  64.     addr.sin_addr.s_addr = inet_addr(server);//按IP初始化  
  65.       
  66.     if(addr.sin_addr.s_addr == INADDR_NONE){//如果输入的是域名  
  67.         phost = (struct hostent*)gethostbyname(server);  
  68.         if(phost==NULL){  
  69.             herror("Init socket s_addr error!");  
  70.             return -1;  
  71.         }  
  72.         addr.sin_addr.s_addr =((struct in_addr*)phost->h_addr)->s_addr;  
  73.     }  
  74.     if(connect(sockfd,(struct sockaddr*)&addr, sizeof(addr))<0)  
  75.     {  
  76.         perror("Connect server fail!");  
  77.         return -1; //0表示成功,-1表示失败  
  78.     }  
  79.     else  
  80.         return sockfd;  
  81. }  
  82. /************************************************************** 
  83.  * 发送消息,如果出错返回-1,否则返回发送的字符长度 
  84.  * sockfd:socket标识,sendBuff:发送的字符串 
  85.  * *********************************************************/  
  86. int send_msg(int sockfd,char * sendBuff)  
  87. {  
  88.     int sendSize=0;  
  89.     if((sendSize=send(sockfd,sendBuff,strlen(sendBuff),0))<=0){  
  90.         herror("Send msg error!");  
  91.         return -1;  
  92.     }else  
  93.         return sendSize;  
  94. }  
  95. /**************************************************************** 
  96.  *接受消息,如果出错返回NULL,否则返回接受字符串的指针(动态分配,注意释放) 
  97.  *sockfd:socket标识 
  98.  * *********************************************************/  
  99. char* recv_msg(int sockfd){  
  100.     char * response;  
  101.     int  flag=0,recLenth=0;  
  102.     response=(char *)malloc(RES_LENGTH);  
  103.     memset(response,0,RES_LENGTH);  
  104.       
  105.     for(flag=0;;)  
  106.     {  
  107.         printf("======recv data:/n");  
  108.         if(( recLenth=recv(sockfd,response+flag,RES_LENGTH-flag,0))==-1 )  
  109.         {  
  110.             free(response);  
  111.             printf("Return value : %d/n", recLenth);  
  112.             perror("Recv msg error : ");  
  113.             return NULL;  
  114.         }  
  115.         else if(recLenth==0)  
  116.             break;  
  117.         else  
  118.         {  
  119.             printf("%d char recieved data : %s./n", recLenth, response+flag);  
  120.             flag+=recLenth;  
  121.             recLenth=0;  
  122.         }  
  123.     }  
  124.     printf("Return value : %d/n", recLenth);  
  125.     response[flag]='/0';  
  126.     return response;  
  127. }  
  128. /************************************************** 
  129.  *关闭连接 
  130.  * **********************************************/  
  131. int close_socket(int sockfd)  
  132. {  
  133.     close(sockfd);  
  134.     return 0;  
  135. }  

 

      TCP Server:

[cpp] view plain copy
  1. #include <unistd.h> /* fork, close */  
  2. #include <stdlib.h> /* exit */  
  3. #include <string.h> /* strlen */  
  4. #include <stdio.h> /* perror, fdopen, fgets */  
  5. #include <sys/socket.h>  
  6. #include <sys/wait.h> /* waitpid */  
  7. #include <netdb.h> /* getaddrinfo */  
  8. #define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)  
  9. #define PORT "4242"  
  10. #define NUM_CHILDREN 3  
  11. #define MAXLEN 1024  
  12. int readline(int fd, char *buf, int maxlen); // forward declaration  
  13. int recvdata(int fd, char *buf, int maxlen); // forward declaration  
  14. int main(int argc, char** argv)  
  15. {  
  16.     int i, n, sockfd, clientfd;  
  17.     int yes = 1;    // used in setsockopt(2)  
  18.     struct addrinfo *ai;  
  19.     struct sockaddr_in *client;  
  20.     socklen_t client_t;  
  21.     pid_t cpid;     // child pid  
  22.     char line[MAXLEN];  
  23.     char cpid_s[32];  
  24.     char welcome[32];  
  25.     /* Create a socket and get its file descriptor -- socket(2) */  
  26.     sockfd = socket(AF_INET, SOCK_STREAM, 0);  
  27.     if (sockfd == -1) {  
  28.         die("Couldn't create a socket");  
  29.     }  
  30.     /* Prevents those dreaded "Address already in use" errors */  
  31.     if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&yes, sizeof(int)) == -1) {  
  32.         die("Couldn't setsockopt");  
  33.     }  
  34.     /* Fill the address info struct (host + port) -- getaddrinfo(3) */  
  35.     if (getaddrinfo(NULL, PORT, NULL, &ai) != 0) {   // get localhost   
  36.         die("Couldn't get address");  
  37.     }  
  38.     /* Assign address to this socket's fd */  
  39.     if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) != 0) {  // only bind on localhost ip  
  40.         die("Couldn't bind socket to address");  
  41.     }  
  42.     /* Free the memory used by our address info struct */  
  43.     freeaddrinfo(ai);  
  44.     /* Mark this socket as able to accept incoming connections */  
  45.     /* printf("Process %d Listening/n", getpid()); */  
  46.     if (listen(sockfd, 10) == -1) {  
  47.         die("Couldn't make socket listen");  
  48.     }  
  49.     printf("One new connection is coming!/n");  
  50.     /* Fork you some child processes. */  
  51.     for (i = 0; i < NUM_CHILDREN; i++) {  
  52.         cpid = fork();  
  53.         if (cpid == -1) {  
  54.             die("Couldn't fork");  
  55.         }  
  56.         if (cpid == 0) { // We're in the child ...  
  57.             for (;;) { // Run forever ...  
  58.                 /* Necessary initialization for accept(2) */  
  59.                 client_t = sizeof client;  
  60.                 /* Blocks! */  
  61.                 printf("Waiting new connection!/n");  
  62.                 clientfd = accept(sockfd, (struct sockaddr *)&client, &client_t);  
  63.                 if (clientfd == -1) {  
  64.                     die("Couldn't accept a connection");  
  65.                 }  
  66.                 /* Send a welcome message/prompt */  
  67.                 bzero(cpid_s, 32);  
  68.                 bzero(welcome, 32);  
  69.                 sprintf(cpid_s, "%d", getpid());  
  70.                 sprintf(welcome, "Child %s echo> ", cpid_s);  
  71.                 send(clientfd, welcome, strlen(welcome), 0);  
  72.                 /* Read a line from the client socket ... */  
  73.                 /* n = readline(clientfd, line, MAXLEN); 
  74.                 if (n == -1) { 
  75.                     die("Couldn't read line from connection"); 
  76.                 }                                                 */  
  77.               
  78.                 n = recvdata(clientfd, line, MAXLEN);  
  79.                 printf("recieve data: %s", line);  
  80.                 /* ... and echo it back */  
  81.                 send(clientfd, line, n, 0);  
  82.                 /* Clean up the client socket */  
  83.                 close(clientfd);  
  84.                 printf("Close client socket./n");  
  85.             }  
  86.         }  
  87.     }  
  88.     /* Sit back and wait for all child processes to exit */  
  89.     while (waitpid(-1, NULL, 0) > 0);  
  90.     /* Close up our socket */  
  91.     close(sockfd);  
  92.     printf("Close server socket./n");  
  93.     return 0;  
  94. }  
  95.     
  96. /** 
  97.  * Simple utility function that reads a line from a file descriptor fd, 
  98.  * up to maxlen bytes -- ripped from Unix Network Programming, Stevens. 
  99.  */  
  100. int readline(int fd, char *buf, int maxlen)  
  101. {  
  102.     int n, rc;  
  103.     char c;  
  104.     for (n = 1; n < maxlen; n++) {  
  105.         if ((rc = read(fd, &c, 1)) == 1) {  
  106.             *buf++ = c;  
  107.             if (c == '/n')  
  108.                 break;  
  109.         } else if (rc == 0) {  
  110.             if (n == 1)  
  111.                 return 0; // EOF, no data read  
  112.             else  
  113.                 break// EOF, read some data  
  114.         } else  
  115.             return -1; // error  
  116.     }  
  117.     *buf = '/0'// null-terminate  
  118.       
  119.     return n;  
  120. }  
  121. int recvdata(int fd, char *buf, int maxlen)  
  122. {  
  123.     return recv(fd, buf, maxlen, 0);  
  124. }  

 

      采用Select的TCP Server:

[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <unistd.h>  
  4. #include <errno.h>  
  5. #include <string.h>  
  6. #include <sys/types.h>  
  7. #include <sys/socket.h>  
  8. #include <netinet/in.h>  
  9. #include <arpa/inet.h>  
  10. #define MYPORT 1234    // the port users will be connecting to  
  11. #define BACKLOG 5     // how many pending connections queue will hold  
  12. #define BUF_SIZE 1024  
  13. int fd_A[BACKLOG];    // accepted connection fd  
  14. int conn_amount;      // current connection amount  
  15. void showclient()  
  16. {  
  17.     int i;  
  18.     printf("client amount: %d/n", conn_amount);  
  19.     for (i = 0; i < BACKLOG; i++) {  
  20.         printf("[%d]:%d  ", i, fd_A[i]);  
  21.     }  
  22.     printf("/n/n");  
  23. }  
  24. int main(void)  
  25. {  
  26.     int sock_fd, new_fd;             // listen on sock_fd, new connection on new_fd  
  27.     struct sockaddr_in server_addr;  // server address information  
  28.     struct sockaddr_in client_addr;  // connector's address information  
  29.     socklen_t sin_size;  
  30.     int yes = 1;  
  31.     char buf[BUF_SIZE];  
  32.     int ret;  
  33.     int i;  
  34.     if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {  
  35.         perror("socket");  
  36.         exit(1);  
  37.     }  
  38.     if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {  
  39.         perror("setsockopt");  
  40.         exit(1);  
  41.     }  
  42.     server_addr.sin_family = AF_INET;         // host byte order  
  43.     server_addr.sin_port = htons(MYPORT);     // short, network byte order  
  44.     server_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP  
  45.     memset(server_addr.sin_zero, '/0'sizeof(server_addr.sin_zero));  
  46.     if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {  
  47.         perror("bind");  
  48.         exit(1);  
  49.     }  
  50.     if (listen(sock_fd, BACKLOG) == -1) {  
  51.         perror("listen");  
  52.         exit(1);  
  53.     }  
  54.     printf("listen port %d/n", MYPORT);  
  55.     fd_set fdsr;  
  56.     int maxsock;  
  57.     struct timeval tv;  
  58.     conn_amount = 0;  
  59.     sin_size = sizeof(client_addr);  
  60.     maxsock = sock_fd;  
  61.     while (1)   
  62.     {  
  63.         // initialize file descriptor set  
  64.         FD_ZERO(&fdsr);  
  65.         FD_SET(sock_fd, &fdsr);  // add fd  
  66.         // timeout setting  
  67.         tv.tv_sec = 30;  
  68.         tv.tv_usec = 0;  
  69.         // add active connection to fd set  
  70.         for (i = 0; i < BACKLOG; i++) {  
  71.             if (fd_A[i] != 0) {  
  72.                 FD_SET(fd_A[i], &fdsr);  
  73.             }  
  74.         }  
  75.         ret = select(maxsock + 1, &fdsr, NULL, NULL, &tv);  
  76.         if (ret < 0) {          // error  
  77.             perror("select");  
  78.             break;  
  79.         } else if (ret == 0) {  // time out  
  80.             printf("timeout/n");  
  81.             continue;  
  82.         }  
  83.         // check every fd in the set  
  84.         for (i = 0; i < conn_amount; i++)   
  85.         {  
  86.             if (FD_ISSET(fd_A[i], &fdsr)) // check which fd is ready  
  87.             {  
  88.                 ret = recv(fd_A[i], buf, sizeof(buf), 0);  
  89.                 if (ret <= 0)   
  90.                 {        // client close  
  91.                     printf("ret : %d and client[%d] close/n", ret, i);  
  92.                     close(fd_A[i]);  
  93.                     FD_CLR(fd_A[i], &fdsr);  // delete fd   
  94.                     fd_A[i] = 0;  
  95.                     conn_amount--;  
  96.                 }  
  97.                 else   
  98.                 {        // receive data  
  99.                     if (ret < BUF_SIZE)  
  100.                         memset(&buf[ret], '/0', 1); // add NULL('/0')  
  101.                     printf("client[%d] send:%s/n", i, buf);  
  102.                 }  
  103.             }  
  104.         }  
  105.         // check whether a new connection comes  
  106.         if (FD_ISSET(sock_fd, &fdsr))  // accept new connection   
  107.         {  
  108.             new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);  
  109.             if (new_fd <= 0)   
  110.             {  
  111.                 perror("accept");  
  112.                 continue;  
  113.             }  
  114.             // add to fd queue  
  115.             if (conn_amount < BACKLOG)   
  116.             {  
  117.                 fd_A[conn_amount++] = new_fd;  
  118.                 printf("new connection client[%d] %s:%d/n", conn_amount,  
  119.                         inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));  
  120.                 if (new_fd > maxsock)  // update the maxsock fd for select function  
  121.                     maxsock = new_fd;  
  122.             }  
  123.             else   
  124.             {  
  125.                 printf("max connections arrive, exit/n");  
  126.                 send(new_fd, "bye", 4, 0);  
  127.                 close(new_fd);  
  128.                 break;     
  129.             }  
  130.         }  
  131.         showclient();  
  132.     }  
  133.     // close other connections  
  134.     for (i = 0; i < BACKLOG; i++)   
  135.     {  
  136.         if (fd_A[i] != 0)   
  137.         {  
  138.             close(fd_A[i]);  
  139.         }  
  140.     }  
  141.     exit(0);  
  142. }  

0
0 0
原创粉丝点击