精华内容
下载资源
问答
  • 原始套接字编程源码

    2011-09-13 15:23:50
    原始套接字编程源码 SOCKET编程 AnalyzeETH_WinPcap
  • 使用原始套接字发送ICMP数据包(ping),并从客户端接收应答数据包。
  • 网络编程,原始套接字编程实验实验。具体功能如下: IP首部的构造;基于原始套接字的分片ICMP ECHO请求发送功能;基于原始套接字的ICMP ECHO响应接收功能;重叠分片的发送功能; 可以用来测试windows系统和Linux系统...
  • 使用raw socket套接字进行编程,局域网内进行监听,可以监听到局域网内所有人的帧。是信息安全课程的网络实验课。
  • 原始套接字程序设计 能运用Winsock提供的API函数接口进行网络程序的编写。 理解原始套接字的工作原理。 在局域网能使用原始套接字进行相关程序设计。 在局域网中使用原始套接字对数据报进行捕获、监听。
  • 原始套接字编程(C++)

    千次阅读 2019-04-02 21:16:48
    1.同上两篇,学校的实验。 但是这第三个实验坑比较多,写了好长时间,百度了好久才写对。 我是先启动的服务器,在启动数据包捕获,最后在启动客户端,这样最初的通信也能捕获到。而且我的客户端与服务器时双向...

    1.同上两篇,学校的实验。

            但是这第三个实验坑比较多,写了好长时间,百度了好久才写对。

            我是先启动的服务器,在启动数据包捕获,最后在启动客户端,这样最初的通信也能捕获到。而且我的客户端与服务器时双向通信,也就是两者都会经过“127.0.0.1”这个地址,所以客户端的消息和服务器的消息都会捕获到。、

            捕获之后根据IP报文结构还有TCP报文结构来推算内容啊,开始位置在哪个地方,这个也与自己定义的头文件有关。

    2.  数据包捕获

    //.h文件
    #pragma once
    
    //IP报文格式
    typedef struct IP {
    	//unsigned char version;//4位IP版本号
    	unsigned char headLen;//4位首部长度
    	unsigned char serviceType;//8位服务类型
    	unsigned short totalLen;//16位总长度
    	unsigned short identifier;//16位标识符
    	unsigned short flags;//3位标志位
    	//unsigned short fragOffset;//13位片偏移
    	unsigned char timeToLive;//8位生存时间
    	unsigned char protocal;//8位协议
    	unsigned short headCheckSum;//16位首部校验和
    	unsigned int sourceAddr;//32位源地址
    	unsigned int destinAddr;//32位目的地址
    }IPHeader;
    
    //TCP报文格式
    typedef struct TCP {
    	unsigned short sourcePort;//16位源端口号
    	unsigned short destinPort;//16位目的端口号
    	unsigned int seqNum;//32位序列号
    	unsigned int ackNum;//32位确认号
    	unsigned char headLen;//4位首部长度
    	//unsigned char resv;//4位保留字
    	unsigned char flags;//8位标志位
    	unsigned short winSize;//16位窗口大小
    	unsigned short checkNum;//16位校验和
    	unsigned short urgPointer;//16位紧急指针
    }TCPHeader;
    
    //.cpp文件
    #include <WinSock2.h>
    #include <iostream>
    #include "headers.h"
    using namespace std;
    
    #pragma comment(lib,"ws2_32.lib")
    
    #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)//将SIO_RCVALL定义为_WSAIOW(IOC_VENDOR,1)
    
    int main() {
    	
    	IP* ip;
    	TCP* tcp;
    
    	WSADATA wsd;
    	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
    		cout << "error:" << WSAGetLastError() << endl;
    		return -1;
    	}
    
    	SOCKET sock;
    	sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    	if (sock == INVALID_SOCKET) {
    		cout << "error:" << WSAGetLastError() << endl;
    		closesocket(sock);
    		WSACleanup();
    		return -2;
    	}
    	BOOL flag = true;
    	if (setsockopt(sock, IPPROTO_IP, 2, (char*)&flag, sizeof(flag)) == SOCKET_ERROR) {
    		cout << "error:" << WSAGetLastError() << endl;
    		closesocket(sock);
    		WSACleanup();
    		return -3;
    	}
    	/*
    	创建了原始套接字后,就要设置套接字选项,这要通过setsocketopt函数来实现,setsocketopt函数的声明如下:
    	int setsocketopt (SOCKET s,int level,int optname,const char FAR *optval,int optlen );
    	参数s是标识套接口的描述字,要注意的是选项对这个套接字必须是有效的。
    	参数Level表明选项定义的层次,对TCP/IP协议族而言,支持SOL_SOCKET、IPPROTO_IP和IPPROTO_TCP层次。
    	参数Optname是需要设置的选项名,这些选项名是在Winsock头文件内定义的常数值。
    	参数optval是一个指针,它指向存放选项值的缓冲区。
    	参数optlen指示optval缓冲区的长度
    	*/
    
    	SOCKADDR_IN addr;
    	addr.sin_family = AF_INET;
    	addr.sin_port = htons(0);
    	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    
    	if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) == SOCKET_ERROR) {
    		cout << "error:" << WSAGetLastError() << endl;
    		closesocket(sock);
    		WSACleanup();
    		return -4;
    	}
    
    	DWORD dwBytesReturned;
    	DWORD dwBufferInLen = 1;
    	//将网卡设置为混听模式,就是接收所有数据
    	if (ioctlsocket(sock, SIO_RCVALL, &dwBufferInLen) == SOCKET_ERROR) {
    		cout << "error:" << WSAGetLastError() << endl;
    		closesocket(sock);
    		WSACleanup();
    		return -5;
    	}
    	/*
    	ioctsocket功能是控制套接口的模式。可用于任一状态的任一套接口。它用于获取与套接口相关的操作参数,而与具体协议或通讯子系统无关。
    	int ioctlsocket( int s, long cmd, u_long * argp);
    	s:一个标识套接口的描述字。
    	cmd:对套接口s的操作命令。
    	argp:指向cmd命令所带参数的指针。
    	*/
    
    	int bytesRecv;
    	char buffer[65535];//接收缓冲区的内容
    	//SOCKADDR_IN from;
    	struct sockaddr_in from;
    	int fromSize = sizeof(from);
    	//循环监听;
    	while (true) {
    		memset(buffer, 0, 65535);
    		bytesRecv = recvfrom(sock, buffer, 65535, 0, (struct sockaddr*) &from, &fromSize);
    		if (bytesRecv == SOCKET_ERROR) {
    			cout << "error:" << WSAGetLastError() << endl;
    			closesocket(sock);
    			WSACleanup();
    			return -6;
    		}
    		/*
    		与recv的功能差不多,都是接收数据,但是from可以适用于UDP,因为多了一个from,你懂的。
    		*/
    
    		ip = (struct IP*)buffer;
    
    		if (ip->protocal == 6) {//过滤其他协议,只留下TCP协议
    			tcp = (struct TCP*)(buffer + (4 * ip->headLen & 0xf0 >> 4));//得到TCP头
    			cout << "Network+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";//网络层数据
    			cout << "IP报文字节数:" << bytesRecv << "\n";
    			cout << "源IP:" << inet_ntoa(*(in_addr*)&ip->sourceAddr) << "\n";
    			cout << "目的IP:" << inet_ntoa(*(in_addr*)&ip->destinAddr) << "\n";
    			cout << "Transportation++++++++++++++++++++++++++++++++++++++++++++++++++++\n";//运输层数据
    			cout << "源端口:" << ntohs(tcp->sourcePort) << "\n";
    			cout << "目的端口:" << ntohs(tcp->destinPort) << "\n";
    			cout << "Applications++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";//应用层数据
    			
    			char* start = buffer + 5 + 4 * ((tcp->headLen & 0xf0) >> 4 | 0);//计算数据头指针,从何处开始数据
    			int dataSize = bytesRecv - 5 - 4 * ((tcp->headLen & 0xf0) >> 4 | 0);//计算数据长度
    			cout << "数据内容:";
    			memcpy(buffer, start, dataSize);
    			for (int i = 0; i < dataSize; i++) {
    				if (buffer[i] >= 32 && buffer[i] < 255) {
    					printf("%c", (unsigned char)buffer[i]);
    				}
    				else {
    					printf(".");
    				}
    			}
    			cout << "\n";
    		}
    	}
    
    }

    3.服务器端

    #include<WinSock2.h>
    #include <iostream>
    using namespace std;
    
    #pragma comment(lib,"ws2_32.lib")
    
    DWORD WINAPI clientChildThread(LPVOID ipParameter) {
    	SOCKET clientSocket = (SOCKET)ipParameter;
    
    	int const CLIENT_MSG_SIZE = 128;//接收缓冲区长度
    	char inMSG[CLIENT_MSG_SIZE];//接收信息的char数组
    	char outMSG[CLIENT_MSG_SIZE];//存储时间的char数组
    	char wx[] = "无效的命令";
    
    	int size;
    	while (true) {
    		memset(inMSG, 0, CLIENT_MSG_SIZE);//接收消息之前清空接收消息数组
    		size = recv(clientSocket, inMSG, CLIENT_MSG_SIZE, 0);//接收消息
    		if (size == SOCKET_ERROR) {//如果接收消息出错
    			cout << "对话中断,错误提示:" << WSAGetLastError() << endl;
    			closesocket(clientSocket);
    			break;
    		}
    		//否则,输出消息
    		cout << "客户端消息:" << inMSG << endl;
    		//如果客户端请求当前时间
    		if (strcmp(inMSG, "当前时间") == 0) {
    			SYSTEMTIME systime = { 0 };
    			GetLocalTime(&systime);//获取系统时间
    			sprintf(outMSG, "%d-%02d-%02d %02d:%02d:%02d",
    				systime.wYear, systime.wMonth, systime.wDay,
    				systime.wHour, systime.wMinute, systime.wSecond);
    			send(clientSocket, outMSG, CLIENT_MSG_SIZE, 0);
    			memset(outMSG, 0, CLIENT_MSG_SIZE);//每次回复之后,清空发送消息数组
    		}
    		//如果客户端要退出连接
    		else if (strcmp(inMSG, "退出连接") == 0) {
    			closesocket(clientSocket);
    			cout << "客户端退出连接成功" << endl;
    			break;
    		}
    		else {
    			send(clientSocket, wx, sizeof(wx), 0);
    		}
    	}
    
    	return 0;
    }
    
    int main() {
    
    	WSADATA wsd;
    	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
    		WSACleanup();
    		return  -1;
    	}
    
    	SOCKET serverSocket;
    	serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	if (serverSocket == INVALID_SOCKET) {
    		cout << "error:" << WSAGetLastError() << endl;
    		WSACleanup();
    		return -2;
    	}
    
    	SOCKADDR_IN server;
    	server.sin_family = AF_INET;
    	server.sin_port = htons(2591);
    	server.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    
    	if (bind(serverSocket, (struct sockaddr*) &server, sizeof(server)) == SOCKET_ERROR) {
    		cout << "error:" << WSAGetLastError() << endl;
    		closesocket(serverSocket);
    		WSACleanup();
    		return -3;
    	}
    
    	if (listen(serverSocket, 2) == SOCKET_ERROR) {
    		cout << "error:" << WSAGetLastError() << endl;
    		closesocket(serverSocket);
    		WSACleanup();
    		return -4;
    	}
    
    	cout << "服务器启动。。。监听中。。。" << endl;
    
    	SOCKET clientSocket;
    	SOCKADDR_IN client;
    	int addrsize = sizeof(SOCKADDR_IN);
    	HANDLE pThread;
    	while (true) {
    
    		clientSocket = accept(serverSocket, (struct sockaddr*) &client, &addrsize);
    		if (clientSocket == INVALID_SOCKET) {
    			cout << "客户端accept失败,错误提示:" << WSAGetLastError() << endl;
    			closesocket(serverSocket);
    			WSACleanup();
    			return -5;
    		}
    		else {
    			cout << "客户端\n"
    				<< inet_ntoa(client.sin_addr)//inet_ntoa将一个十进制网络字节序转换为点分十进制IP格式的字符串。
    				<< "\n通过端口:\n"
    				<< ntohs(client.sin_port)//ntohs将一个16位数由网络字节顺序转换为主机字节顺序
    				<< "\n连接成功" << endl;
    
    			pThread = CreateThread(NULL, 0, clientChildThread, (LPVOID)clientSocket, 0, NULL);
    			/*
    			lpsa:线程句柄的安全性,比如子进程是否可以继承这个线程句柄,一般设置为NULL
    			cbStack:线程栈大小,一般取0表示默认大小
    			lpStartAddr:线程入口函数
    			lpvThreadParam:线程入口函数的参数
    			fdwCreate:控制线程创建的标志,一般为0,表示线程立即启动。也可以选择可以挂起,使用CREATE_SUSPENDED,之后在代码中使用ResumeThread启动。
    			lpIDThread:线程的ID值,接收线程返回的ID
    			*/
    			if (pThread == NULL) {
    				cout << "创建子进程失败。" << endl;
    				break;
    			}
    
    			CloseHandle(pThread);
    
    		}
    
    	}
    
    	closesocket(serverSocket);
    	closesocket(clientSocket);
    	WSACleanup();
    
    	return 0;
    
    }

    4.客户端

    #include<WinSock2.h>
    #include <iostream>
    using namespace std;
    
    #pragma comment(lib,"ws2_32.lib")
    
    int main() {
    
    	WSADATA wsd;//定义	WSADATA对象
    	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {//初始化WSA
    		WSACleanup();
    		return -1;
    	}
    
    	SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	if (clientSocket == INVALID_SOCKET) {
    		cout << "error:" << WSAGetLastError() << endl;
    		WSACleanup();
    		return -2;
    	}
    
    	SOCKADDR_IN client;
    	client.sin_family = AF_INET;
    	client.sin_port = htons(2591);
    	client.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    
    	int const SERVER_MSG_SIZE = 128;
    	char inMSG[SERVER_MSG_SIZE] = { 0 };//用户输入的消息
    	char outMSG[SERVER_MSG_SIZE];//要发送给服务器的消息
    
    	//连接服务器失败
    	if (connect(clientSocket, (struct sockaddr*) &client, sizeof(client)) < 0) {
    		cout << "error:" << WSAGetLastError() << endl;
    		closesocket(clientSocket);
    		WSACleanup();
    		return -3;
    	}
    	//连接服务器成功
    	else {
    		cout << "连接服务器成功。。。。。。\n" << endl;
    		while (true) {
    			memset(outMSG, 0, SERVER_MSG_SIZE);
    			cout << "请输入请求。。。。。。:" << endl;
    			cin >> outMSG;
    			send(clientSocket, outMSG, SERVER_MSG_SIZE, 0);
    			if (strcmp(outMSG, "退出连接") == 0) {
    				break;
    			}
    			int size = recv(clientSocket, inMSG, SERVER_MSG_SIZE, 0);
    			cout << "服务器端回答:" << inMSG << endl;
    			memset(inMSG, 0, SERVER_MSG_SIZE);
    		}
    	}
    
    	closesocket(clientSocket);
    	WSACleanup();
    
    	system("pause");
    	return 0;
    
    }

     

    展开全文
  • 原始套接字编程实例

    2017-11-08 02:20:00
    原始套接字编程实例 #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <netdb.h> #include <s...

    原始套接字编程实例


    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <unistd.h>
    #include <netdb.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #include <netinet/ip.h>
    //#include <linux/ip.h>
    #include <linux/tcp.h>
    #define DESTPORT 80 /* 要攻击的端口 */
    #define LOCALPORT 8888 /*管理员打开的端口*/
    void send_tcp(int sockfd,struct sockaddr_in *addr);
    unsigned short check_sum(unsigned short *addr,int len);
    int main(int argc,char **argv)
    {
    int sockfd;
    struct sockaddr_in addr;
    struct hostent *host;
    int on=1;
    if(argc!=2){ 
    fprintf(stderr,"Usage:%s hostname\n\a",argv[0]);
    exit(1);
    }
    bzero(&addr,sizeof(struct sockaddr_in));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(DESTPORT);

    if(inet_aton(argv[1],&addr.sin_addr)==0){ 
    host=gethostbyname(argv[1]); 
    if(host==NULL) { 
    fprintf(stderr,"HostName Error:%s\n\a",hstrerror(h_errno));
    exit(1); 

    addr.sin_addr=*(struct in_addr *)(host->h_addr_list[0]);
    }


    /**** 使用IPPROTO_TCP创建一个TCP的原始套接字 ****/
    sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_TCP);
    if(sockfd<0){ 
    fprintf(stderr,"Socket Error:%s\n\a",strerror(errno)); 
    exit(1);
    }

    /******** 设置IP数据包格式,告诉系统内核模块IP数据包由我们自己来填写 ***/

    setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));

    /**** 没有办法,只用超级护用户才可以使用原始套接字 *********/

    setuid(getpid());


    /********* 发送炸弹了!!!! ****/

    send_tcp(sockfd,&addr);

    }


    /******* 发送炸弹的实现 *********/
    void send_tcp(int sockfd,struct sockaddr_in *addr)
    {

    char buffer[100]; 

    /**** 用来放置我们的数据包 ****/

    struct ip *ip;
    struct tcphdr *tcp;
    int head_len;

    /******* 我们的数据包实际上没有任何内容,所以长度就是两个结构的长度 ***/

    head_len=sizeof(struct ip)+sizeof(struct tcphdr);
    bzero(buffer,100);

    /******** 填充IP数据包的头部,还记得IP的头格式吗? ******/ 

    ip=(struct ip*)buffer;

    ip->ip_v=4; /** IPVERSION版本一般的是 4 **/
    ip->ip_hl=sizeof(struct ip)>>2; /** IP数据包的头部长度 **/
    ip->ip_tos=0; /** 服务类型 **/
    ip->ip_len=htons(head_len); /** IP数据包的长度 **/
    ip->ip_id=0; /** 让系统去填写吧 **/
    ip->ip_off=0; /** 和上面一样,省点时间 **/ 
    ip->ip_ttl=255; /**MAXTTL 最长的时间 255 **/
    ip->ip_p=IPPROTO_TCP; /** 我们要发的是 TCP包 **/ 
    ip->ip_sum=0; /** 校验和让系统去做 **/
    ip->ip_dst=addr->sin_addr; /** 我们攻击的对象 **/

    /******* 开始填写TCP数据包 *****/
    tcp=(struct tcphdr *)(buffer +sizeof(struct ip));
    tcp->source=htons(LOCALPORT);
    tcp->dest=addr->sin_port; /** 目的端口 **/
    tcp->seq=random();//这里就是seq的数值了。
    tcp->ack_seq=0;//这里是ack_seq
    tcp->doff=5;
    tcp->syn=1; 
    /** 我要建立连接 **/
    tcp->check=0;//这里可以用while之类的循环来达到穷举seq的目的。
    ip->ip_src.s_addr=inet_addr("192.168.1.200");//这里是管理员的IP 
    /** 什么都让系统做了,也没有多大的意思,还是让我们自己来校验头部吧,节约时间的话把校验合去掉 */
    tcp->check=check_sum((unsigned short *)tcp,sizeof(struct tcphdr)); 
    //sendto(sockfd,buffer,head_len,0,(const struct sockaddr *)addr, sizeof(struct sockaddr_in));
    sendto(sockfd,buffer,head_len,0,(const struct sockaddr *)addr, sizeof(struct sockaddr_in));
    }

    unsigned short check_sum(unsigned short *addr,int len)
    {
    register int nleft=len;
    register int sum=0;
    register short *w=addr; 
    short answer=0;
    while(nleft>1){
    sum+=*w++; nleft-=2;
    }
    if(nleft==1)

    *(unsigned char *)(&answer)=*(unsigned char *)w;
    sum+=answer;

    sum=(sum>>16)+(sum&0xffff);
    sum+=(sum>>16);
    answer=~sum;
    return(answer);

    }





    /*

    hostent的定义如下:
    struct hostent {
    char *h_name;
    char **h_aliases;
    int h_addrtype;
    int h_length;
    char **h_addr_list;
    #define h_addr h_addr_list[0]
    };
    struct hostent
    h_name – 地址的正式名称。
    h_aliases – 空字节-地址的预备名称的指针。
    h_addrtype –地址类型; 通常是AF_INET。  
    h_length – 地址的比特长度。
    h_addr_list – 零字节-主机网络地址指针。网络字节顺序。
    h_addr - h_addr_list中的第一地址。


    本文转自陈仲阳0 51CTO博客,原文链接:http://blog.51cto.com/wolfword/1225370

    展开全文
  • 一些专业术语 SOCKET_STEAM 流式套接字TCP SOCKET_DGRAM 数据包套接字UDP SOCKET_RAW 原始套接字 IPPROTO_IP IP协议 IPPROOTO_ICMP INTERNAT 控制消息协议:配合原始套接字可以实现ping功能 IPP...

    一些专业术语

    SOCKET_STEAM  流式套接字TCP

    SOCKET_DGRAM  数据包套接字UDP

    SOCKET_RAW  原始套接字

    IPPROTO_IP  IP协议

    IPPROOTO_ICMP INTERNAT  控制消息协议:配合原始套接字可以实现ping功能

    IPPROTO_IGMP INTERNET  网关服务协议:多播有关

     

     

    在AF_INET地址族下,有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW三种套接字类型。SOCK_STREAM也就是通常所说的TCP,而SOCK_DGRAM则是通常所说的UDP,而SOCK_RAW则是用于提供一些较低级的控制的;第3个参数依赖于第2个参数,用于指定套接字所用的特定协议,设为0表示使用默认的协议。

     

    RAW SOCKET能够对较低层次的协议直接访问,网络监听技术很大程度上依赖于它。本文介绍了利用RAW SOCKET捕获网络底层数据包的步骤和方法,并开发了一个程序模型来进一步探讨了利用RAW SOCKET捕获数据包的方法。

    原始套接字编程

    1 引言

     

    随着信息技术的快速发展,网络已成为信息交换的主要手段,一些网络新业务在不断地兴起,如电子商务、移动支付等,这些都对网络安全提出了较高的要求。与此同时,黑客对网络的攻击从未停止,网络的安全问题变得日趋严峻。

    很多网络攻击都是从监听开始的,网络监听最重要一步就是捕获局域网中的数据帧,因此,研究数据捕获技术对于保障网络安全有着重要的意义。

     

    2 RAW SOCKET简介

        同一台主机不同进程可以用进程号来唯一标识,但是在网络环境下进程号并不能唯一标识该进程。TCP/IP主要引入了网络地址、端口和连接等概念来解决网络间进程标识问题。套接字(Socket)是一个指向传输提供者的句柄,TCP/IP协议支持3种类型的套接字,分别是流式套接字、数据报式套接字和原始套接字。

     

    流式套接字(SOCKET_STREAM)提供了面向连接、双向可靠的数据流传输服务。数据报式套接字(SOCKET_ DGRAM)提供了无连接服务,不提供无错保证。原始套接字(SOCKET_RAW)允许对较低层次的协议直接访问,比如IP、 ICMP协议,它常用于检验新的协议实现,或者访问现有服务中配置的新设备,因为RAW SOCKET可以自如地控制Windows下的多种协议,能够对网络底层的传输机制进行控制,所以可以应用原始套接字来操纵网络层和传输层应用。比如,我们可以通过RAW SOCKET来接收发向本机的ICMP、IGMP协议包,或者接收TCP/IP栈不能够处理的IP包,也可以用来发送一些自定包头或自定协议的IP包。网络监听技术很大程度上依赖于SOCKET_RAW。

     

    3 RAW SOCKET编程

    要使用原始套接字,必须经过创建原始套接字、设置套接字选项和创建并填充相应协议头这三个步骤,然后用send、WSASend函数将组装好的数据发送出去。接收的过程也很相似,只是需要用recv或WSARecv函数接收数据。下面介绍使用RAW SOCKET编程的几个步骤。

     

    3.1 创建原始套接字

        我们可以用socket或WSASocket函数来创建原始套接字,因为原始套接字能直接控制底层协议,因此只有属于“管理员”组的成员,才有权创建原始套接字。下面是用socket函数创建原始套接字的代码。

     

    SOCKET sock;

     

    Sock=socket (AF_INET, SOCK_RAW, IPPROTO_UDP);

     

        上述创建原始套接字的代码使用的是UDP协议,如果要使用其它的协议,比如ICMP、IGMP、IP等协议,只需要把相应的参数改为IPPROTO_ICM、IPPROTO_ IGMP、IPPROTO_IP就可以了。另外,IPPROTO_UDP、IPPROTO_IP、IPPROTO_RAW这几个协议标志要求使用套接字选项IP_HDRINCL,而目前只有Windows 2000和Windows XP提供了对IP_HDRINCL的支持,这意味着在Windows 2000以下平台创建原始套接字时是不能使用IP、UDP、TCP协议的。

     

    3.2 设置套接字选项

        创建了原始套接字后,就要设置套接字选项,这要通过setsocketopt函数来实现,setsocketopt函数的声明如下:

     

    int setsocketopt (

    SOCKET s,

    int level,

    int optname,

    const char FAR *optval,

    int optlen

    );

     

    在该声明中,参数s是标识套接口的描述字,要注意的是选项对这个套接字必须是有效的。参数Level表明选项定义的层次,对TCP/IP协议族而言,支持SOL_SOCKET、IPPROTO_IP和IPPROTO_TCP层次。参数Optname是需要设置的选项名,这些选项名是在Winsock头文件内定义的常数值。参数optval是一个指针,它指向存放选项值的缓冲区。参数optlen指示optval缓冲区的长度

     

    3.3 创建并填充相应协议头

       这一步就是创建IP和TCP协议头的数据结构,根据相关协议的定义进行编写即可,下面是一个TCP协议头的数据结构。

    struct TCP

    {

        unsigned short   tcp_sport;   

        unsigned short   tcp_dport;    

        unsigned int     tcp_seq;      

        unsigned int     tcp_ack;     

        unsigned char    tcp_lenres; 

        unsigned char    tcp_flag;     

        unsigned short   tcp_win;      

        unsigned short   tcp_sum;       

        unsigned short   tcp_urp;       

    };

    4 一个利用RAW SOCKET捕获网络数据包的程序模型

       下面介绍一个利用RAW SOCKET捕获网络数据包的程序模型。这个程序模型演示了如何使用RAW SOCKET捕获局域网中的数据包,它完成了网络底层数据的接收,能显示源地址、目标地址、源端口、目标端口和接收的字节数等信息。这个程序模型也说明了网络监听的基本原理,给捕获局域网中的数据包提供了一种方法,即先把网卡设置为混杂模式,然后利用RAW SOCKET接收IP层的数据。

        程序在Visual C++.net 2003中调试并编译通过,运行环境为以太网, 程序代码可同时在Linux与windows环境下编译和运行,当然在编译时需要不同的头文件以及需要对代码作相应的改动。本程序模型在Windows下能直接运行,如果在Linux下运行,则需要先用手工把网卡设置为混杂模式,在root权限下用如下命令设置:ifconfig eth0 promisc。

        在Unix/Linux下程序要包含以下这几个进行调用系统和网络函数的头文件:

    #include〈stdio.h〉

    #include〈sys/socket.h〉

    #include〈netinet/in.h〉

    #include〈arpa/inet.h〉

    #include"headers.h"

    为了方便基于Berkeley套接口的已有源程序的移植,Windows Sockets支持许多Berkeley头文件。这些Berkeley头文件被包含在WINSOCK2.H中,所以一个Windows Sockets应用程序只需包含WINSOCK2.H头文件就足够了,这也是目前推荐使用的一种方法。在Windows平台下程序改用以下这几个头文件:

    #include "stdafx.h"

    #include<stdio.h>

    #include<Winsock2.h>

    #include"headers.h"

    headers.h是自己编写的头文件,它的作用是定义IP和TCP包的头结构。在程序中首先定义几个变量和结构,然后调用函数socket()建立socket连接,主要代码如下:

    int _tmain(int argc, _TCHAR* argv[])

    {

    int sock,bytes_recieved,fromlen;

    char buffer[65535];

    struct sockaddr_in from;

    struct ip *ip;

    struct tcp *tcp;

    sock=socket(AF_INET,SOCK_RAW,IPPROTO_TCP);

         ……

    return 0;

    }

     

    程序的第二步用一个while(1)语句来建立一个死循环,用来不停地接收网络信息。首先用函数sizeof()取出一个socket结构的长度,这个参数是recvfrom()函数所必须的。从建立的socket连接中接收数据是通过函数recvfrom()是来实现的,因为recvfrom()函数需要一个sockaddr数据类型,所以用了一个强制类型转换,代码如下:fromlen=sizeof(from);

    bytes_recieved=recvfrom(sock,buffer,sizeof(buffer),0,(struct sockaddr*)&from,&fromlen);

    接下来用一条语句把接收到的数据转化为我们预先定义的结构,以便于查看,代码为:

    ip=(struct ip *)buffer

        还要用一条语句来指向TCP头,因为接收的数据中,IP头的大小是固定的4字节,所以用IP长度乘以4就能指向TCP头部分,代码为:

    tcp=(struct tcp *)(buffer+(4*ip->ip_length))

        最后就可以用打印语句把接收的字节数、数据的源地址、目标地址、源端口、目标端口、IP头长度和协议的类型输出来。

     

      

    设计任务分析

     

    (一)实验环境

     

    操作系统:Windows 编程工具及集成开发环境:VC++ 

    (二)实验目的和要求

     

    实验目的:掌握原始套接字编程。 

    实验要求:完成下列功能: 

    (1)利用RAW SOCKET捕获网络数据包的程序模型SOCKET_STREAM 流式套接SOCKET_DGRAM 

     

    (2)能够抓取第二节课的并发服务器程序的服务器端或客户端的应用层数据,即:时

    间值,打印输出。

     

     

    二、设计方案

     

    同一台主机不同进程可以用进程号来唯一标识,但是在网络环境下进程号并不能唯一标2识该进程。TCP/IP主要引入了网络地址、端口和连接等概念来解决网络间进程标识问题。套接字(Socket)是一个指向传输提供者的句柄,TCP/IP协议支持种类型的套接字,分别是流式套接字、数据报式套接字和原始套接字。流式套接字(SOCKET_STREAM)提供面向连接、双向可靠的数据流传输服务。数据报式套接字(SOCKET_ DGRAM)提供了无连接不提供无错保证。原始套接字(SOCKET_RAW)允许对较低层次的协议直接访问,比如IP、ICMP

    协议,它常用于检验新的协议实现,或者访问现有服务中配置的新设备,因为RAW SOCKET可以自如地控制Windows下的多种协议,能够对网络底层的传输机制进行控制,所以可以应用原始套接字来操纵网络层和传输层应用。比如,我们可以通过RAW SOCKET来接收发向本机的ICMP、IGMP协议包,或者接收TCP/IP栈不能够处理的IP包,也可以用来定包头或自定协议的IP包。网络监听技术很大程度上依赖于SOCKET_RAW。

     本实验采用原始套接字进行捕获通过本主机的包并对本主机的包进行处理


     

     头文件

    ip.h

     

    详细代码:

     //定义标准的的TCP头和IP头

     

    #define URG 0x20 

    #define ACK 0x10 

    #define PSH 0x08 

    #define RST 0x04 

    #define SYN 0x02 

    #define FIN 0x01 

     

    typedef struct _iphdr //定义IP首部

     

    unsigned char h_verlen; //4位首部长度+4位IP版本号 

    unsigned char tos; //8位服务类型TOS 

    unsigned short total_len; //16位总长度(字节)

    unsigned short ident; //16位标识 

    unsigned short frag_and_flags; //3位标志位

    unsigned char ttl; //8位生存时间 TTL 

    unsigned char proto; //8位协议(TCP, UDP 或其他)  

    unsigned short checksum; //16位IP首部校验和 

    unsigned int sourceIP; //32位源IP地址  

    unsigned int destIP; //32位目的IP地址 

    }IP_HEADER; 

     

     

     

    typedef struct _tcphdr //定义TCP首部 

    {  

    USHORT th_sport; //16位源端口 

    USHORT th_dport; //16位目的端口

    unsigned int th_seq; //32位序列号 

    unsigned int th_ack; //32位确认号 

    unsigned char th_lenres; //4位首部长度/6位保留字 

    unsigned char th_flag; //6位标志位 

    USHORT th_win; //16位窗口大小 

    USHORT th_sum; //16位校验和 

    USHORT th_urp; //16位紧急数据偏移量 

    }TCP_HEADER;

     

    // 定义ICMP首部

    typedef struct icmp_hdr 

    {  

    unsigned char  i_type;  // 类型 

    unsigned char  i_code; // 代码

    unsigned short i_cksum; // 校验码

    unsigned short i_id; // 非标准的ICMP首部 

    unsigned short i_seq; 

    unsigned long  timestamp; 

    }ICMP_HEADER; 

     

    typedef struct udp_hdr // 8 Bytes 定义udp首部 

    unsigned short uh_sport; 

    unsigned short uh_dport; 

    unsigned short uh_len; 

    unsigned short uh_sum; 

    }UDP_HEADER; 

     

    源文件

    详细代码:

     

    #include<stdio.h> 

    #include<Winsock2.h> 

    #pragma comment(lib,"ws2_32") 

    #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1) 

    struct ip // 定义IP首部

     unsigned char h_verlen;  // 4位首部长度,4位IP版本号

     unsigned char tos; // 8位服务类型TOS  

     unsigned short ip_length; // 16位总长度(字节)

     unsigned short ident;// 16位标识

     unsigned short frag_and_flags; // 3位标志位

    unsigned char ttl; // 8位生存时间TTL 

    unsigned char proto; // 8位协议 (TCP, UDP 或其他) 

     unsigned short checksum; // 16位IP首部校验和

    unsigned int sourceIP; // 32位源IP地址

    unsigned int destIP; // 32位目的IP地址

     };

     // 定义TCP首部

     

    struct tcp 

    USHORT th_sport; // 16位源端口 

    USHORT th_dport; // 16位目的端口

    unsigned int th_seq; // 32位序列号

    unsigned int th_ack; // 32位确认号

    unsigned char th_lenres; // 4位首部长度/6位保留字 

    unsigned char th_flag; // 6位标志位

    USHORT th_win; // 16位窗口大小

    USHORT th_sum; // 16位校验和 

    USHORT th_urp; // 16位紧急数据偏移量

    };  

    void main() 

     

    int sock,bytes_recieved,fromlen; 

    char buffer[65535]; 

    struct sockaddr_in from;  

    struct ip *ip; 

    struct tcp *tcp; 

    struct ip *ip; 

     struct tcp *tcp;  

    WORD wVersionRequested; //版本号

    WSADATA wsaData; //启动SOCKET的 

    int err;  

    wVersionRequested = MAKEWORD( 2, 2 );//建立版本

    err = WSAStartup( wVersionRequested,&wsaData );//启用socket 

     

    if ( err != 0 ) //如果返回值不等于0,那么表示出错,直截退出程序

     return; 

     }  

    sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP);  

    bool flag=true;  

    setsockopt(sock, IPPROTO_IP, 2 , (char*)&flag, sizeof(flag));  

    sockaddr_in addr; 

    addr.sin_family = AF_INET; 

    addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); //IP设置

    addr.sin_port=htons(0);  

    if(SOCKET_ERROR==bind(sock,(sockaddr *)&addr,sizeof(addr))) //绑定

    closesocket(sock); 

     printf("绑定失败!"); 

    exit(0);  

     

    DWORD dwBytesRet; 

    DWORD dwVal=1;  

    ioctlsocket(sock, SIO_RCVALL, &dwVal); //设置网卡为混听模式

    int i=0; 

    while(true) {  

    fromlen=sizeof(from); 

    bytes_recieved=recvfrom(sock,buffer,sizeof(buffer),0,(struct 

    sockaddr*)&from,&fromlen); //接收数据 

    i++; 

    ip=(struct ip *)buffer; //得到ip头

    if(ip->proto==6) //过滤其他协议,只留下TCP协议

    tcp=(struct tcp *)(buffer+(4*ip->h_verlen&0xf0>>4)); //得到tcp头

    printf("Ip包字节数:%d\n",bytes_recieved); //打印ip数据包长度

    printf("源IP:%s\n", inet_ntoa(*(in_addr*)&ip->sourceIP)); //打印源IP 

    printf("目的IP:%s\n", inet_ntoa(*(in_addr*)&ip->destIP)); //打印目的IP 

    printf("源端口:%d\n",ntohs(tcp->th_sport)); //打印源端口

    printf("目的端口:%d\n",ntohs(tcp->th_dport)); //打印目的端口

    printf("TCP的数据内容:"); 

    char* ptr=buffer+5+ 4*((tcp->th_lenres&0xf0)>>4|0); //计算数据头指针

    int cpysize=bytes_recieved-5- 4*((tcp->th_lenres&0xf0)>>4|0);//计算数据长度 

    memcpy(buffer, ptr, cpysize); //取出数据

    for(int i = 0; i < cpysize  i++) //打印数据

    if(buffer[i] >= 32 && buffer[i] < 255) 

     { printf("%c", (unsigned char)buffer[i]); 

    }else{ 

    printf("."); 

    }  

    printf("\n");  

     

    转载于:https://my.oschina.net/u/3344205/blog/858801

    展开全文
  • 原始套接字编程

    2021-09-29 17:46:14
    实验原始套接字编程 一、 实验目的 1.了解Winsock原始套接字编程功能和特点。 2.掌握Winsock原始套接字编程基本方法和步骤。 3.理解ICMP协议在网络中的具体应用及其实现原理。 二、实验内容 1.利用原始套接字编程...

    实验四 原始套接字编程

    一、 实验目的

    1.了解Winsock原始套接字编程功能和特点。
    2.掌握Winsock原始套接字编程基本方法和步骤。
    3.理解ICMP协议在网络中的具体应用及其实现原理。

    二、实验内容

    1.利用原始套接字编程实现ping命令:
    运用原始套接字编程技术,通过ICMP协议所提供的回送请求(echo request)和回送应答(echo reply)报文实现检测目的主机的可达性与状态。
    2.(选做)在实现ping命令的基础上,参照教材例6.9设计一个局域网扫描工具。

    三、实验原理

    Ping的工作原理
    ping程序是用来探测主机到主机之间是否可通信,如果不能ping到某台主机,表明不能和这台主机建立连接。ping 使用的是ICMP协议,它发送ICMP回送请求消息给目的主机。ICMP协议规定:目的主机必须返回ICMP回送应答消息给源主机。如果源主机在- -定时间内收到应答,则认为主机可达。
    ICMP协议通过IP协议发送的,IP协议是无连接的,不可靠的数据包协议。因此,保证数据送达的工作应该由其他的模块来完成。
    使用ping命令可以检测指定设备的在线状态,但在程序中通常不会直接执行ping命令而是通过Socket编程的方式向目标ip地址发送icmp请求包,然后返回等待结果。

    四、实验步骤

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    五、实验小结

    附:程序源代码

    #include "stdafx.h"
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdio.h>
    #include <stdlib.h>
    #pragma comment(lib,"ws2_32.lib")
    #define WIN32_LEAN_AND_MEAN 
    #define IP_RECORD_ROUTE  0x7
    #define ICMP_MIN 8
    #define ICMP_ECHOREPLY 0
    #define ICMP_ECHO 8
     
    #define DEF_PACKET_SIZE  32       
    #define MAX_PACKET       1024     
    #define MAX_IP_HDR_SIZE  60       
     
    typedef struct iphdr {
    	unsigned int h_len : 4;						
    	unsigned int version : 4;					
    	unsigned char tos;							
    	unsigned short total_len;				
    	unsigned short ident;						
    	unsigned short frag_and_flags;		
    	unsigned char ttl;								
    	unsigned char proto;						
    	unsigned short checksum;				
     
    	unsigned int sourceIP;
    	unsigned int destIP;
    }IpHeader;
     
    USHORT checksum(USHORT *buffer, int size) {
    	unsigned long cksum = 0;
     
    	while (size > 1) {
    		cksum += *buffer++;
    		size -= sizeof(USHORT);
    	}
    	if (size) {
    		cksum += *(UCHAR*)buffer;
    	}
    	cksum = (cksum >> 16) + (cksum & 0xffff);
    	cksum += (cksum >> 16);
    	return (USHORT)(~cksum);
    }
     
    typedef struct _ihdr {
    	BYTE i_type;									
    	BYTE i_code;									
    	USHORT i_cksum;								
    	USHORT i_id;									
    	USHORT i_seq;								
    	ULONG timestamp;							
    }IcmpHeader;
     
    void fill_icmp_data(char * icmp_data, int datasize){
     
    	IcmpHeader *icmp_hdr;
    	char *datapart;
    
    	icmp_hdr = (IcmpHeader*)icmp_data;
    
    	icmp_hdr->i_type = ICMP_ECHO;									
    	icmp_hdr->i_code = 0;													
    	icmp_hdr->i_id = (USHORT)GetCurrentThreadId();			
    	icmp_hdr->i_cksum = 0;													
    	icmp_hdr->i_seq = 0;														
    	datapart = icmp_data + sizeof(IcmpHeader);					
    
    	memset(datapart, 'E', datasize - sizeof(IcmpHeader));
    }
     
    int decode_icmp_resp(char *buf, int bytes, sockaddr_in *from, DWORD tid)
    {
    	IpHeader *iphdr;
    	IcmpHeader *icmphdr;
    	unsigned short iphdrlen;
    	iphdr = (IpHeader*)buf;
    	iphdrlen = iphdr->h_len * 4;
    	if (bytes < iphdrlen + ICMP_MIN)
    	{
    		return -1;
    	}
    	icmphdr = (IcmpHeader*)(buf + iphdrlen);
    	if (icmphdr->i_type != ICMP_ECHOREPLY)
    	{
    		return -2;
    	}
    	if (icmphdr->i_id != (USHORT)tid)
    	{
    		return -3;
    	}
    	int time = GetTickCount() - (icmphdr->timestamp);
    	if (time >= 0)
    	{
    		return time;
    	}
    	else
    	{
    		return -4;
    	}
    }
     
    int ping(const char *ip, DWORD timeout)
    {
    	WSADATA wsa;
    	SOCKET sockRaw = NULL;
    	sockaddr_in dest, from;
    	hostent *hp;
    	int datasize;
    	char *dest_ip;
    	char *icmp_data = NULL;
    	char *recvbuf = NULL;
    	USHORT seq_no = 0;
    	int retval;
    	int ret;
    	
    	if (WSAStartup(MAKEWORD(2, 1), &wsa) != 0){
    		ret = -1000;
    		goto FIN;
    	}
    
    	sockRaw = WSASocket(AF_INET,
    		SOCK_RAW,
    		IPPROTO_ICMP,
    		NULL, 0, WSA_FLAG_OVERLAPPED);
    	if (sockRaw == INVALID_SOCKET) {
    		ret = -2;
    		goto FIN;
    	}
    	int bread = setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
    		sizeof(timeout));
    	if (bread == SOCKET_ERROR) {
    		ret = -3;
    		goto FIN;
    	}
    	bread = setsockopt(sockRaw, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout,
    		sizeof(timeout));
    	if (bread == SOCKET_ERROR) {
    		ret = -4;
    		goto FIN;
    	}
    	memset(&dest, 0, sizeof(dest));
     
    	unsigned int addr = 0;					
    	hp = gethostbyname(ip);				
    	if (!hp){
    		addr = inet_addr(ip);  
    	}
    	if ((!hp) && (addr == INADDR_NONE)) {
    		ret = -5; 
    		goto FIN;
    	}
    	if (hp != NULL)
    		memcpy(&(dest.sin_addr), hp->h_addr, hp->h_length);
    	else
    		dest.sin_addr.s_addr = addr;
     
    	if (hp)
    		dest.sin_family = hp->h_addrtype;
    	else
    		dest.sin_family = AF_INET;
    	dest_ip = inet_ntoa(dest.sin_addr);
     
    	datasize = DEF_PACKET_SIZE;
    	datasize = datasize + sizeof(IcmpHeader);
    	char icmp_dataStack[MAX_PACKET];
    	char recvbufStack[MAX_PACKET];
    	icmp_data = icmp_dataStack;
    	recvbuf = recvbufStack;
    	if (!icmp_data)
    	{
    		ret = -6;
    		goto FIN;
    	}
    	memset(icmp_data, 0, MAX_PACKET);
    	fill_icmp_data(icmp_data, datasize);
    	DWORD startTime = GetTickCount();
    	((IcmpHeader*)icmp_data)->timestamp = startTime;
    	((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data, datasize);
    	int bwrote;
    	bwrote = sendto(sockRaw, icmp_data, datasize, 0, (struct sockaddr*)&dest, sizeof(dest));
    	if (bwrote == SOCKET_ERROR)
    	{
    		if (WSAGetLastError() != WSAETIMEDOUT)
    		{
    			ret = -7;
    			goto FIN;
    		}
    	}
    	if (bwrote < datasize)
    	{
    		ret = -8;
    		goto FIN;
    	}
    	LARGE_INTEGER ticksPerSecond;
    	LARGE_INTEGER start_tick;
    	LARGE_INTEGER end_tick;
    	double elapsed;
    	QueryPerformanceFrequency(&ticksPerSecond);
    	QueryPerformanceCounter(&start_tick);
    	int fromlen = sizeof(from);
    	while (1)
    	{
    		retval = recvfrom(sockRaw, recvbuf, MAX_PACKET, 0, (struct sockaddr*)&from, &fromlen);
    		if (retval == SOCKET_ERROR)
    		{
    			if (WSAGetLastError() == WSAETIMEDOUT)
    			{
    				ret = -1;
    				goto FIN;
    			}
    			ret = -9;
    			goto FIN;
    		}
    		int time = decode_icmp_resp(recvbuf, retval, &from, GetCurrentThreadId());
    		if (time >= 0)
    		{
    			QueryPerformanceCounter(&end_tick);
    			elapsed = ((double)(end_tick.QuadPart - start_tick.QuadPart) / ticksPerSecond.QuadPart);
    			ret = (int)(elapsed * 1000);
    			goto FIN;
    		}
    		else if (GetTickCount() - startTime >= timeout || GetTickCount() < startTime)
    		{
    			ret = -1;
    			goto FIN;
    		}
    	}
    FIN:
    	closesocket(sockRaw);
    	WSACleanup();
    	return ret;
    }
     
    int main(int argc, char **argv) {
    	printf("ping %s\n", argv[1]);
    	int ret = ping(argv[1], 5000);
    	if (ret >= 0)
    	{
    		printf("%s在线,用时%dms\n", argv[1], ret);
    	}
    	else
    	{
    		printf("%d\n", ret);
    	}
    	system("pause");
    	return 0;
    }
    
    展开全文
  • 这篇文章主要介绍了Python原始套接字编程实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM...
  • 程序实现步骤: 1、初始化Windows Sockets网络环境 ...3、创建原始套接字 4、定义IP和ICMP头部数据结构 5、发送报文 6、接收报文 其中ICMP回显请求与回显应答报文结构如下图: typedef struct IcmpHead
  • Linux网络编程——原始套接字编程

    万次阅读 多人点赞 2015-03-27 17:47:16
    原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据。区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有的数据帧...
  • 熟悉原始套接字编程的基本流程 理解ping程序的实现机制 理解ICMP协议的基于作用和报文格式。 完成原始套接字的配置。 【实验内容】 1.构造ICMP协议首部结构 2.构造ICMP回射请求结构。 3. 构造ICMP回射应答...
  • Linux网络编程:原始套接字编程及实例分析 转载 2016年07月29日 11:25:11 标签: socket / 网络编程 / 编程 / linux / 888 编辑 删除 Linux网络编程:原始套接字编程及实例分析 一、原始套接字能干什么? ...
  • 原始套接字实现ping

    2013-01-01 09:31:04
    原始套接字实现ICMP的ping功能,包括原始套接字的创建,选项设置,数据接收等详解。
  • 原始套接字Sniffer程序

    2013-02-16 22:37:52
    基于原始套接字编写的Sniffer程序。
  • 因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_RAW进行数据发送。 使用SOCK_RAW的优势是,可以对数据包进行完整的修改,可以处理IP层上的所有数据包,对各字段进行修改,而不受UDP和...
  • 采用C++语言,基于原始套接字实现了Ping和Tracert命令。发送主机通过ping程序给目标主机发送ICMP的回声请求报文,并根据收到的ICMP回声应答报文来确定网络的连通性。Tracert(跟踪路由)是路由跟踪实用程序,用于...
  • 【网络编程】---C++实现原始套接字捕获数据包

    千次阅读 多人点赞 2019-12-18 18:09:21
    【网络编程】—C++实现原始套接字捕获数据包 引言:通过创建原始套接字,获取本地可用的Ip地址,选择捕获数据包使用的网卡,绑定本地地址后,设置网卡为混杂模式,实现循环接收并显示数据来实现捕获数据包。 ...
  • 1、首先要明白的是:你发送的TCP数据到底是怎样构造的吧? 2、TCP数据报的构成方式:   这是TCP头部-------如果无TCP的选项其头部大小为20个字节; 3、下面要明白IP头部的大小: ... ip->ip_dst.s_addr=i
  • 基本TCP套接字编程

    2017-10-27 21:45:42
    基本套接字函数
  • 原始套接字与sniffer

    2015-03-20 17:26:37
    原始套接字与sniffer 2009-05-11 23:40:30 分类: LINUX 下面是原文件附的代码.我运行过,很好. 文件: source.rar 大小: 7KB 下载: 下载 ...
  • 链路层原始套接字编程-总结

    千次阅读 2014-09-10 13:51:44
    1、链路层原始套接字创建方法:socket(PF_PACKET, SOCK_RAW, htons(protocol)),其中protocal参数为关心的协议类型。 2、默认情况下网卡只处理目的地址是本机网卡地址的包,可通过设置混杂模式,使网卡将收到的所有...
  • 在一个应用程序创建套接字进行通信时,socket()中的通信类型参数会让用户从数据流、数据报、原始类型中作出选择。其中数据流的传输方式就是基于TCP,而TCP因其数据流、可靠的特点适用于大多数情况。 流式套接字...
  • 原始套接字 --11. 后记 来源:http://linuxc.51.net 作者:hoyt (2001-05-08 11:26:09) 10. 原始套接字 我们在前面已经学习过了网络程序的两种套接字(SOCK_STREAM,SOCK_DRAGM).在这一章 里面我们一起来...
  • 流式套接字编程

    千次阅读 2014-10-06 10:26:21
    原始套接字(RAW); 2、流式套接字是面向连接的、提供双向、有序、无重复且无记录边界的数据流服务,适用于处理大量数据,可靠性高,但开销也大。 3、服务器端编程步骤: (1)调用...
  • 基本TCP套接字总结

    千次阅读 2015-01-22 11:56:44
    网络编程之前也写过一些小程序,但是都是照猫画虎.按照书中实例,一个一个照抄的....框架只是为了使用方便和代码复用,但要真正对网络编程理解深刻,原始函数的作用也每个步骤的细节还是要自己多多琢磨。 TCP/IP的基本
  •  其实意思就是对原本套接字的功能增强,如果你只调用socket()函数,只是有一般的功能,你去使用setsockopt函数有另外的一些功能,就比如玩吃鸡,你一开始的状态是没有任何武器的,你只有一双手,没有任何武器,这...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,378
精华内容 3,751
关键字:

原始套接字编程实验