Linux socket编程(TCP,UDP,RAW)
2011-07-25 13:36
435 查看
1、TCP socket编程
服务器端程序:TCP_server.c#include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <string.h> #include <stdlib.h> #define SERVPORT 8080 #define BACKLOG 10 /*最大客户端连接数*/ #define MAXDATASIZE 100 int main() { int sockfd,client_fd,addr_size,recvbytes; char rcv_buf[MAXDATASIZE],snd_buf[MAXDATASIZE]; char * val; struct sockaddr_in server_addr; struct sockaddr_in client_addr; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ perror("socket:"); exit(1); } server_addr.sin_family=AF_INET; server_addr.sin_port=htons(SERVPORT); server_addr.sin_addr.s_addr = INADDR_ANY; /*自动探测IP*/ memset(&(server_addr.sin_zero),0,8); if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))== -1) { perror("bind:"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror("listen:"); exit(1); } while(1) { addr_size = sizeof(struct sockaddr_in); if((client_fd=accept(sockfd,(struct sockaddr *)&client_addr,&addr_size))==-1) { /*非阻塞模式*/ perror("accept:"); continue; } printf("connection from:%s\n",(char *)inet_ntoa(client_addr.sin_addr)); /*inet_ntoa不能重载*/ if (!fork()) { /*子进程处理客户端连接*/ if ((recvbytes=recv(client_fd, rcv_buf, MAXDATASIZE, 0)) ==-1) { perror("recv:"); exit(1); } rcv_buf[recvbytes]='\0'; printf("recv:%s\n",rcv_buf); *snd_buf='\0'; strcat(snd_buf,"welcome"); if (send(client_fd,snd_buf,strlen(snd_buf), 0) == -1) { perror("send:"); exit(1); } printf("send:%s\n",snd_buf); close(client_fd); exit(1); } close(client_fd); } return 0; /*由于是无限循环监听,所以不关闭sockfd*/ }
客户端程序:TCP_client.c
#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netdb.h> #include <string.h> #define SERVPORT 8080 #define MAXDATASIZE 100 int main(int argc, char *argv[]) { int sockfd, recvbytes; char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello*/ char snd_buf[MAXDATASIZE]; struct hostent *host; struct sockaddr_in server_addr; if (argc < 3) { printf("Usage:%s [ip address] [any string]\n",argv[0]); return 1; } *snd_buf = '\0'; strcat(snd_buf,argv[2]); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket:"); exit(1); } server_addr.sin_family=AF_INET; server_addr.sin_port=htons(SERVPORT); inet_pton(AF_INET,argv[1],&server_addr.sin_addr); memset(&(server_addr.sin_zero),0,8); if(connect(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr))==-1) { perror("connect:"); exit(1); } if (send(sockfd,snd_buf,sizeof(snd_buf), 0) == -1) { perror("send:"); exit(1); } printf("send:%s\n",snd_buf); if ((recvbytes=recv(sockfd, rcv_buf, MAXDATASIZE, 0)) ==-1) { perror("recv:"); exit(1); } rcv_buf[recvbytes] = '\0'; printf("recv:%s\n",rcv_buf); close(sockfd); return 0; }
Makefile:
all:TCP_server TCP_client TCP_server:TCP_server.c gcc -o TCP_server TCP_server.c -lpthread TCP_client:TCP_client.c gcc -o TCP_client TCP_client.c clean: rm -f TCP_server rm -f TCP_client
2、UDP socket编程
服务器端程序:UDP_server.c#include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <string.h> #include <stdlib.h> #define SERVPORT 8080 #define MAXDATASIZE 100 int main() { int sockfd,client_fd,addr_size,recvbytes; char rcv_buf[MAXDATASIZE],snd_buf[MAXDATASIZE]; char * val; struct sockaddr_in server_addr; struct sockaddr_in client_addr; if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){ perror("socket:"); exit(1); } server_addr.sin_family=AF_INET; server_addr.sin_port=htons(SERVPORT); server_addr.sin_addr.s_addr = INADDR_ANY; memset(&(server_addr.sin_zero),0,8); if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))== -1) { perror("bind:"); exit(1); } while(1) { addr_size = sizeof(struct sockaddr); if (!fork()) { if ((recvbytes=recvfrom(sockfd,rcv_buf,MAXDATASIZE,0, (struct sockaddr*)&client_addr,&addr_size)) ==-1) { perror("recv:"); exit(1); } rcv_buf[recvbytes]='\0'; printf("recv:%s\n",rcv_buf); *snd_buf='\0'; strcat(snd_buf,"welcome"); if (sendto(sockfd,snd_buf,strlen(snd_buf),0, (struct sockaddr*)&client_addr,addr_size) == -1) { perror("send:"); exit(1); } printf("send:%s\n",snd_buf); exit(1); } } close(sockfd); return 0; }
客户端程序:UDP_client.c
#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netdb.h> #include <string.h> #define SERVPORT 8080 #define MAXDATASIZE 100 int main(int argc, char *argv[]) { int server_sockfd, recvbytes,addr_size; char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello*/ char snd_buf[MAXDATASIZE]; struct hostent *host; struct sockaddr_in server_addr; if (argc < 3) { printf("Usage:%s [ip address] [any string]\n",argv[0]); return 1; } *snd_buf = '\0'; /*收到的网络数据结尾没有'\0'*/ strcat(snd_buf,argv[2]); if ((server_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket:"); exit(1); } server_addr.sin_family=AF_INET; server_addr.sin_port=htons(SERVPORT); inet_pton(AF_INET,argv[1],&server_addr.sin_addr); memset(&(server_addr.sin_zero),0,8); addr_size=sizeof(struct sockaddr); if (sendto(server_sockfd,snd_buf,sizeof(snd_buf),0, (struct sockaddr*)&server_addr,addr_size) == -1) { perror("send:"); exit(1); } printf("send:%s\n",snd_buf); if ((recvbytes=recvfrom(server_sockfd,rcv_buf,MAXDATASIZE,0, (struct sockaddr*)&server_addr,&addr_size)) ==-1) { perror("recv:"); exit(1); } rcv_buf[recvbytes] = '\0'; printf("recv:%s\n",rcv_buf); close(server_sockfd); return 0; }
Makefile:
all:UDP_server UDP_client UDP_server:UDP_server.c gcc -o UDP_server UDP_server.c UDP_client:UDP_client.c gcc -o UDP_client UDP_client.c clean: rm -f UDP_server 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))
#include <stdio.h> #include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <linux/if_ether.h> #include <linux/in.h> #include <stdlib.h> /*使用exit函数要添加stdlib.h库*/ #define MAXDATASIZE 2048 int main() { int sock, n_read, proto; char buffer[MAXDATASIZE]; char *ethhead, *iphead, *tcphead,*udphead, *icmphead, *p; if((sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) < 0) { perror("socket:"); exit(1); } while(1) { n_read = recvfrom(sock, buffer, 2048, 0, NULL, NULL); /* 14 6(dest)+6(source)+2(type or length)+[数据段尾部2B] + 20 ip header=12(其他位)+4(source_ip)+4(dest_ip)[+40(可选项)] + 8 icmp(不定),tcp(20~60) or udp(8) header = 42 */ if(n_read < 42) { perror("Incomplete header, packet corrupt:"); continue; } ethhead = buffer; p = ethhead; printf("MAC: %.2X:%02X:%02X:%02X:%02X:%02X==>" "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", p[6]&0XFF, p[7]&0XFF, p[8]&0XFF, p[9]&0XFF, p[10]&0XFF, p[11]&0XFF, p[0]&0XFF, p[1]&0XFF, p[2]&0XFF,p[3]&0XFF, p[4]&0XFF, p[5]&0XFF); iphead = ethhead + 14; p = iphead + 12; printf("IP: %d.%d.%d.%d => %d.%d.%d.%d\n", p[0]&0XFF, p[1]&0XFF, p[2]&0XFF, p[3]&0XFF, p[4]&0XFF, p[5]&0XFF, p[6]&0XFF, p[7]&0XFF); proto = (iphead + 9)[0]; p = iphead + 20; printf("Protocol:"); switch(proto) { case IPPROTO_ICMP: printf("ICMP\n");break; case IPPROTO_IGMP: printf("IGMP\n");break; case IPPROTO_IPIP: printf("IPIP\n");break; case IPPROTO_TCP : case IPPROTO_UDP : printf("%s,", proto == IPPROTO_TCP ? "TCP": "UDP"); printf("source port: %u,",(p[0]<<8)&0XFF00 | p[1]&0XFF); printf("dest port: %u\n", (p[2]<<8)&0XFF00 | p[3]&0XFF); break; case IPPROTO_RAW : printf("RAW\n");break; default:printf("Unkown, please query in include/linux/in.h\n"); } } }
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头部 =不定
相关文章推荐
- Linux socket编程(TCP,UDP,RAW)
- linux socket编程之TCP与UDP
- linux socket编程之TCP与UDP
- linux socket编程以及简单的tcp,udp的例子
- linux socket编程之TCP与UDP
- Linux高级编程复习 第九章 信号量同步_socket网络编程基础_TCP_UDP
- linux网络编程Socket之TCP与UDP
- linux socket编程之TCP与UDP
- linux socket编程 TCP和UDP实例
- Linux socket编程示例(最简单的TCP和UDP两个例子)
- Linux C Socket编程原理及tcp, udp简单实例
- linux socket编程之TCP与UDP
- linux socket编程TCP&UDP
- 简单的IPv6 UDP/TCP socket编程 -- 两台Linux实现简单的ipv6通信
- linux下C/C++网络编程基本:socket实现tcp和udp的例子
- linux socket编程之TCP与UDP
- linux socket编程之TCP与UDP
- linux socket编程之TCP与UDP
- TCP UDP及socket编程学习(一)
- socket编程——TCP/UDP数据传输