1. 程式人生 > >網絡駭客入門之UDP編程

網絡駭客入門之UDP編程

UDP

網絡駭客入門之UDP編程


本文列出了在LINUX系統下使用C語言進行UDP收發操作的常用函數和用法


註意:

創建套接字時,系統會分配一個臨時端口,默認主動發起服務請求,作為服務器時可修改為被動

發送數據時,不需要用bind綁定端口(當然綁定也可以)

接收數據時,如果不想知道發送者的信息(如:IP地址,端口等),可以不創建發送者結構體,然後recvfrom的後兩個參數寫NULL

因為網絡上的字節序是大端格式(低地址存高字節),所以在發送數據和顯示接收的數據時要用htonl/htons和ntohl/ntohs轉換(即host to net long/short和net to host long/short)

如果是IP地址,常用inet_pton/inet_ntop

inet_pton(AF_INET, "10.220.4.100", &dst_addr.sin_addr);

char cli_ip[16] = "";

inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, sizeof(cli_ip));

當然inet_addr("10.220.4.100")也可以,不過年紀大了,不中用了。

1發送數據

1.1.頭文件

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>


main()函數


1.2創建套接字

int sockedfd = 0;

sockedfd = socket(AF_INET,SOCK_DGRAM,0);//創建UDP套接字

if(sockedfd < 0)

{

perror("socket");

exit(-1);

}


1.3發送消息緩沖區

char buf[100]="hello";


1.4填充發送結構體

struct sockaddr_in dst_addr;//目的結構體

bzero(&dst_addr,sizeof(dst_addr));

dst_addr.sin_family = AF_INET;//協議類型

dst_addr.sin_port = htons(8080);//目的端口

inet_pton(AF_INET, "10.220.4.100", &dst_addr.sin_addr); //目的IP地址


1.5發送數據,返回發送的字節數

int len = sendto(sockedfd,buf,strlen(buf),0,(struct sockaddr *)&dst_addr,sizeof(dst_addr));

printf("len = ==%d\n",len);


1.6

關閉套接字

close(sockedfd);


2接收數據

2.1創建套接字

int sockedfd = 0;

sockedfd = socket(AF_INET,SOCK_DGRAM,0);//創建UDP套接字

if(sockedfd < 0)

{

perror("socket");

exit(-1);

}

//填充接收結構體

struct sockaddr_in my_addr;//接收結構體

bzero(&my_addr,sizeof(my_addr));

my_addr.sin_family = AF_INET;//協議類型

my_addr.sin_port = htons(8080);//接收端口

my_addr.sin_addr.s_addr = htonl(INADDR_ANY);//接收IP地址設為任意IP

int err;

//綁定接收端口,便於其它機器訪問

err = bind(sockedfd,(struct sockaddr*)&my_addr,sizeof(my_addr));

if(err != 0)

{

perror("bind");

close(sockedfd);

exit(-1);

}

//定義接收緩沖區

char buf[100]="";

//創建發送者結構體,用於儲存發送者信息

struct sockaddr_in src_addr;

bzero(&src_addr,sizeof(src_addr));

//發送者結構體的大小

int len=sizeof(src_addr);

//從套接字接收數據

recvfrom(sockedfd,buf,sizeof(buf),0,(struct sockaddr*)&src_addr,&len);

//顯示發送端口

printf("port == %d\n",ntohs(src_addr.sin_port));

關閉套接字

close(sockedfd);


下面介紹一下類似於迅雷等下載器的tftp協議

TFTP即簡單文本傳輸協議,工作在應用層,基於UDP,不進行用戶認證

只要往69號端口按固定的消息格式發送一條文件請求,另一邊的服務器就會把請求的文件發送過來

消息格式:操作碼+文件名+0+傳輸模式+0其中操作碼為2字節(1讀,2寫,3數據,4確認,5錯誤)

數據包格式為操作碼3(2B)+編號(2B)+數據,收到數據包後要發送確認包 操作碼4(2B)+塊編號

如果數據包小於516字節則說明接收完畢。

具體程序如下:

前面的步驟都一樣了

char sendbuf[512]="";

int len = sprintf(sendbuf,"%c%c%s%c%s%c",0,1,“hello.txt”,0,"octet",0);//"octet"為二進制模式,“netascii”為文本模式

sendto(sockfd,sendbuf,len,0,(struct sockaddr*)&dest_addr,sizeof(dest_addr));

發送完了立刻進行接收

do{

//接收服務器發送的內容

len = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr*)&client_addr, &cliaddr_len);

cmd = recv_buf[1];

if( cmd == 3 )//是否為數據包

{

//包編號是否和上次相等

if( (unsigned short)(p_num+1) == ntohs(*(unsigned short*)(recv_buf+2) ))

{

write(fd, recv_buf+4, len-4);

p_num = ntohs(*(unsigned short*)(recv_buf+2));

printf("recv:%d\n", p_num);//十進制方式打印包編號

}

recv_buf[1] = 4;//操作碼+1從數據包變為確認包

sendto(sockfd, recv_buf, 4, 0, (struct sockaddr*)&client_addr, sizeof(client_addr));

}

else if( cmd == 5 ) //是否為錯誤應答

{

close(fd);

close(sockfd);

unlink(argv[2]);

printf("error:%s\n", recv_buf+4);

return 0;

}

}while(len == 516); //如果收到的數據小於516則認為出錯

close(fd);

close(sockfd);

網絡駭客入門之UDP編程