1、TCP socket编程

服务器端程序:TCP_server.c

[cpp]  view plain copy
  1. #include <stdio.h>   
  2. #include <sys/socket.h>  
  3. #include <sys/types.h>  
  4. #include <netinet/in.h>  
  5. #include <string.h>  
  6. #include <stdlib.h>   
  7.   
  8. #define SERVPORT 8080                                 
  9. #define BACKLOG 10                                  /*最大客户端连接数*/   
  10. #define MAXDATASIZE 100   
  11. int main() {   
  12.     int sockfd,client_fd,addr_size,recvbytes;         
  13.     char rcv_buf[MAXDATASIZE],snd_buf[MAXDATASIZE];  
  14.     char * val;  
  15.     struct sockaddr_in server_addr;                      
  16.     struct sockaddr_in client_addr;                   
  17.     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){      
  18.         perror("socket:");   
  19.         exit(1);   
  20.     }   
  21.     server_addr.sin_family=AF_INET;     
  22.     server_addr.sin_port=htons(SERVPORT);             
  23.     server_addr.sin_addr.s_addr = INADDR_ANY;       /*自动探测IP*/  
  24.     memset(&(server_addr.sin_zero),0,8);   
  25.     if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))== -1)   
  26.     {   
  27.         perror("bind:");   
  28.         exit(1);   
  29.     }     
  30.     if (listen(sockfd, BACKLOG) == -1)   
  31.     {   
  32.         perror("listen:");   
  33.         exit(1);   
  34.     }   
  35.     while(1)   
  36.     {      
  37.         addr_size = sizeof(struct sockaddr_in);      
  38.         if((client_fd=accept(sockfd,(struct sockaddr *)&client_addr,&addr_size))==-1)   
  39.         {                                                /*非阻塞模式*/   
  40.             perror("accept:");   
  41.             continue;   
  42.         }      
  43.         printf("connection from:%s\n",(char *)inet_ntoa(client_addr.sin_addr));   
  44.                                                          /*inet_ntoa不能重载*/     
  45.         if (!fork())   
  46.         {                                                /*子进程处理客户端连接*/   
  47.             if ((recvbytes=recv(client_fd, rcv_buf, MAXDATASIZE, 0)) ==-1)   
  48.             {   
  49.                 perror("recv:");   
  50.                 exit(1);   
  51.             }           
  52.         rcv_buf[recvbytes]='\0';  
  53.         printf("recv:%s\n",rcv_buf);  
  54.   
  55.         *snd_buf='\0';  
  56.         strcat(snd_buf,"welcome");  
  57.             if (send(client_fd,snd_buf,strlen(snd_buf), 0) == -1)      
  58.             {  
  59.                 perror("send:");   
  60.                 exit(1);  
  61.             }  
  62.         printf("send:%s\n",snd_buf);  
  63.   
  64.             close(client_fd);   
  65.             exit(1);   
  66.         }      
  67.         close(client_fd);      
  68.     }   
  69.     return 0;                               /*由于是无限循环监听,所以不关闭sockfd*/   
  70. }   

客户端程序:TCP_client.c

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>   
  3. #include <sys/socket.h>   
  4. #include <netdb.h>  
  5. #include <string.h>  
  6.   
  7. #define SERVPORT 8080   
  8. #define MAXDATASIZE 100   
  9. int main(int argc, char *argv[])   
  10. {   
  11.     int sockfd, recvbytes;   
  12.     char rcv_buf[MAXDATASIZE];          /*./client 127.0.0.1 hello*/   
  13.     char snd_buf[MAXDATASIZE];   
  14.     struct hostent *host;   
  15.     struct sockaddr_in server_addr;   
  16.     if (argc < 3)   
  17.     {   
  18.         printf("Usage:%s [ip address] [any string]\n",argv[0]);   
  19.         return 1;   
  20.     }   
  21.     *snd_buf = '\0';                          
  22.     strcat(snd_buf,argv[2]);  
  23.   
  24.     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)   
  25.     {   
  26.         perror("socket:");  
  27.         exit(1);   
  28.     }   
  29.     server_addr.sin_family=AF_INET;   
  30.     server_addr.sin_port=htons(SERVPORT);   
  31.     inet_pton(AF_INET,argv[1],&server_addr.sin_addr);  
  32.     memset(&(server_addr.sin_zero),0,8);   
  33.     if(connect(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr))==-1)   
  34.     {   
  35.         perror("connect:");   
  36.         exit(1);   
  37.     }   
  38.   
  39.     if (send(sockfd,snd_buf,sizeof(snd_buf), 0) == -1)      
  40.     {           
  41.         perror("send:");  
  42.         exit(1);   
  43.     }  
  44.     printf("send:%s\n",snd_buf);   
  45.   
  46.     if ((recvbytes=recv(sockfd, rcv_buf, MAXDATASIZE, 0)) ==-1)   
  47.     {   
  48.         perror("recv:");   
  49.         exit(1);   
  50.     }   
  51.     rcv_buf[recvbytes] = '\0';   
  52.     printf("recv:%s\n",rcv_buf);   
  53.   
  54.     close(sockfd);   
  55.     return 0;   
  56. }   

Makefile:

[cpp]  view plain copy
  1. all:TCP_server TCP_client  
  2. TCP_server:TCP_server.c  
  3.     gcc -o TCP_server TCP_server.c -lpthread  
  4. TCP_client:TCP_client.c  
  5.     gcc -o TCP_client TCP_client.c  
  6. clean:  
  7.     rm -f TCP_server  
  8.     rm -f TCP_client  

2、UDP socket编程

服务器端程序:UDP_server.c

[cpp]  view plain copy
  1. #include <stdio.h>   
  2. #include <sys/socket.h>  
  3. #include <sys/types.h>  
  4. #include <netinet/in.h>  
  5. #include <string.h>  
  6. #include <stdlib.h>   
  7. #define SERVPORT 8080                                 
  8. #define MAXDATASIZE 100   
  9. int main() {   
  10.     int sockfd,client_fd,addr_size,recvbytes;         
  11.     char rcv_buf[MAXDATASIZE],snd_buf[MAXDATASIZE];  
  12.     char * val;  
  13.     struct sockaddr_in server_addr;                       
  14.     struct sockaddr_in client_addr;                   
  15.     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){      
  16.         perror("socket:");   
  17.         exit(1);   
  18.     }   
  19.     server_addr.sin_family=AF_INET;     
  20.     server_addr.sin_port=htons(SERVPORT);             
  21.     server_addr.sin_addr.s_addr = INADDR_ANY;         
  22.     memset(&(server_addr.sin_zero),0,8);   
  23.     if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))== -1)   
  24.     {   
  25.         perror("bind:");   
  26.         exit(1);   
  27.     }     
  28.   
  29.     while(1)   
  30.     {      
  31.         addr_size = sizeof(struct sockaddr);      
  32.   
  33.         if (!fork())   
  34.         {                                                  
  35.             if ((recvbytes=recvfrom(sockfd,rcv_buf,MAXDATASIZE,0,  
  36.                                    (struct sockaddr*)&client_addr,&addr_size)) ==-1)   
  37.             {   
  38.                 perror("recv:");   
  39.                 exit(1);   
  40.             }  
  41.             rcv_buf[recvbytes]='\0';  
  42.         printf("recv:%s\n",rcv_buf);  
  43.   
  44.         *snd_buf='\0';  
  45.         strcat(snd_buf,"welcome");  
  46.             if (sendto(sockfd,snd_buf,strlen(snd_buf),0,  
  47.                                    (struct sockaddr*)&client_addr,addr_size) == -1)      
  48.             {  
  49.                 perror("send:");   
  50.                 exit(1);  
  51.             }  
  52.         printf("send:%s\n",snd_buf);  
  53.             exit(1);   
  54.         }      
  55.     }   
  56.     close(sockfd);     
  57.     return 0;                         
  58. }   

客户端程序:UDP_client.c

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>   
  3. #include <sys/socket.h>   
  4. #include <netdb.h>  
  5. #include <string.h>  
  6.   
  7. #define SERVPORT 8080   
  8. #define MAXDATASIZE 100   
  9. int main(int argc, char *argv[])   
  10. {   
  11.     int server_sockfd, recvbytes,addr_size;   
  12.     char rcv_buf[MAXDATASIZE];          /*./client 127.0.0.1 hello*/   
  13.     char snd_buf[MAXDATASIZE];   
  14.     struct hostent *host;   
  15.     struct sockaddr_in server_addr;   
  16.     if (argc < 3)   
  17.     {   
  18.         printf("Usage:%s [ip address] [any string]\n",argv[0]);   
  19.         return 1;   
  20.     }   
  21.     *snd_buf = '\0';                        /*收到的网络数据结尾没有'\0'*/  
  22.     strcat(snd_buf,argv[2]);  
  23.   
  24.     if ((server_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)   
  25.     {   
  26.         perror("socket:");  
  27.         exit(1);   
  28.     }   
  29.     server_addr.sin_family=AF_INET;   
  30.     server_addr.sin_port=htons(SERVPORT);   
  31.     inet_pton(AF_INET,argv[1],&server_addr.sin_addr);  
  32.     memset(&(server_addr.sin_zero),0,8);   
  33.   
  34.     addr_size=sizeof(struct sockaddr);  
  35.     if (sendto(server_sockfd,snd_buf,sizeof(snd_buf),0,  
  36.                           (struct sockaddr*)&server_addr,addr_size) == -1)      
  37.     {           
  38.         perror("send:");  
  39.         exit(1);   
  40.     }  
  41.     printf("send:%s\n",snd_buf);   
  42.   
  43.     if ((recvbytes=recvfrom(server_sockfd,rcv_buf,MAXDATASIZE,0,  
  44.                          (struct sockaddr*)&server_addr,&addr_size)) ==-1)   
  45.     {   
  46.         perror("recv:");   
  47.         exit(1);   
  48.     }   
  49.     rcv_buf[recvbytes] = '\0';   
  50.     printf("recv:%s\n",rcv_buf);   
  51.   
  52.     close(server_sockfd);   
  53.     return 0;   
  54. }   

Makefile:

[cpp]  view plain copy
  1. all:UDP_server UDP_client  
  2. UDP_server:UDP_server.c  
  3.     gcc -o UDP_server UDP_server.c   
  4. UDP_client:UDP_client.c  
  5.     gcc -o UDP_client UDP_client.c  
  6. clean:  
  7.     rm -f UDP_server  
  8.     rm -f UDP_client  

3、raw socket编程

截获ip数据包:         socket(AF_INET, SOCK_RAW, IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP)

截获以太网数据帧:socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <sys/socket.h>  
  4. #include <sys/types.h>  
  5. #include <linux/if_ether.h>  
  6. #include <linux/in.h>  
  7. #include <stdlib.h>                               /*使用exit函数要添加stdlib.h库*/  
  8. #define MAXDATASIZE 2048  
  9.   
  10. int main()  
  11. {  
  12.           
  13.         int sock, n_read, proto;          
  14.         char buffer[MAXDATASIZE];  
  15.         char  *ethhead, *iphead, *tcphead,*udphead, *icmphead, *p;  
  16.           
  17.     if((sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) < 0)  
  18.         {  
  19.         perror("socket:");  
  20.             exit(1);  
  21.         }  
  22.           
  23.     while(1)   
  24.     {  
  25.             n_read = recvfrom(sock, buffer, 2048, 0, NULL, NULL);  
  26.             /* 
  27.             14   6(dest)+6(source)+2(type or length)+[数据段尾部2B] 
  28.             + 
  29.             20   ip header=12(其他位)+4(source_ip)+4(dest_ip)[+40(可选项)] 
  30.             + 
  31.             8   icmp(不定),tcp(20~60) or udp(8) header 
  32.             = 42 
  33.             */  
  34.         if(n_read < 42)   
  35.         {  
  36.             perror("Incomplete header, packet corrupt:");  
  37.                 continue;  
  38.         }  
  39.                   
  40.             ethhead = buffer;  
  41.             p = ethhead;  
  42.                 printf("MAC: %.2X:%02X:%02X:%02X:%02X:%02X==>"  
  43.                            "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n",  
  44.                 p[6]&0XFF, p[7]&0XFF, p[8]&0XFF, p[9]&0XFF, p[10]&0XFF, p[11]&0XFF,  
  45.                 p[0]&0XFF, p[1]&0XFF, p[2]&0XFF,p[3]&0XFF, p[4]&0XFF, p[5]&0XFF);  
  46.   
  47.                 iphead = ethhead + 14;    
  48.                 p = iphead + 12;  
  49.           
  50.             printf("IP: %d.%d.%d.%d => %d.%d.%d.%d\n",  
  51.             p[0]&0XFF, p[1]&0XFF, p[2]&0XFF, p[3]&0XFF,  
  52.             p[4]&0XFF, p[5]&0XFF, p[6]&0XFF, p[7]&0XFF);  
  53.                 proto = (iphead + 9)[0];  
  54.                 p = iphead + 20;  
  55.                 printf("Protocol:");  
  56.                 switch(proto)  
  57.                 {  
  58.                     case IPPROTO_ICMP: printf("ICMP\n");break;  
  59.                     case IPPROTO_IGMP: printf("IGMP\n");break;  
  60.                     case IPPROTO_IPIP: printf("IPIP\n");break;  
  61.                     case IPPROTO_TCP :  
  62.                     case IPPROTO_UDP :   
  63.                     printf("%s,", proto == IPPROTO_TCP ? "TCP""UDP");   
  64.                     printf("source port: %u,",(p[0]<<8)&0XFF00 |  p[1]&0XFF);  
  65.                     printf("dest port: %u\n", (p[2]<<8)&0XFF00 | p[3]&0XFF);  
  66.                     break;  
  67.                 case IPPROTO_RAW : printf("RAW\n");break;  
  68.                 default:printf("Unkown, please query in include/linux/in.h\n");  
  69.             }  
  70.     }  
  71. }  


raw_socket.c运行后可用ping www.baidu.com测试

4、socket编程总结

(1)raw_socket编程步骤:socket→recvfrom

(2)tcp_socket编程步骤:

          服务器端:socket→初始化struct  sockaddr_in→bind→listen→[accept→send→recv] 

          客户端:    socket→初始化struct  sockaddr_in→connect→[recv→send]

(3)udp_socket编程步骤:

          服务器端:socket→初始化struct  sockaddr_in→bind→[recvfrom→sendto]

          客户端:    socket→初始化struct  sockaddr_in→[sendto→recvfrom]

          注:[]表示循环

(4)网络封包各层报头

          mac层头部+尾部   =14+2

          ip层头部                    =20~60

          tcp头部                      =20~60

          udp头部                    =8

          icmp头部                  =不定

Logo

更多推荐