端口扫描分为哪几类?原理是什么?_端口扫描socket

hacker|
264

c++语言写个端口扫描需要用到的函数

基本上就只需要利用一下socket库中的函数就够了

基本步骤:

1. 创建socket。int socket(int domain, int type, int protocol);

2. 绑定本地端口。int bind(int socket, const struct sockaddr *address, socklen_t address_len);

3. 连接主机。int connect(int socket, const struct sockaddr *address, socklen_t address_len);

4. 发送数据。ssize_t send(int socket, const void *buffer, size_t length, int flags);

UDP和TCP在send方法上稍有区别。

另外,我这里的函数是摘自BSD平台的socket库,不同的操作系统下面方法名字和参数可能稍有不同,但这几个步骤都是一样的。

什么是端口扫描?

端口扫描是指某些别有用心的人发送一组端口扫描消息,试图以此侵入某台计算机,并了解其提供的计算机网络服务类型(这些网络服务均与端口号相关)。端口扫描是计算机解密高手喜欢的一种方式。攻击者可以通过它了解到从哪里可探寻到攻击弱点。实质上,端口扫描包括向每个端口发送消息,一次只发送一个消息。接收到的回应类型表示是否在使用该端口并且可由此探寻其弱点。

扫描器是一种自动检测远程或本地主机安全性弱点的程序,通过使用扫描器可以不留痕迹地发现远程服务器的各种TCP端口的分配及提供的服务和它们的软件版本,这就能让人们间接的或直观的了解到远程主机所存在的安全问题。

详见 百度百科

goby的使用中如何扫描一个c段ip

1.资产收集

自动探测当前网络空间存活的 IP 及解析域名到 IP,轻量且快速的分析出端口对应的协议、Mac 地址、证书、应用产品、厂商等信息。

子域名扫描

自动爬取子域名,AXFR 监测,二级域名字典爆破,关联域名查询。同时支持连接 FOFA,扩大数据源。

网站截图

通过截图,快速判断网站系统应用,无须再一一打开。

注:该功能基于 Chrome 截图插件实现,需要预安装 Chrome 浏览器。

深度分析

发现非标准端口或非标准应用系统资产,进行深入的应用识别。在实战场景中非常有效。

代理扫描

通过 socket5 代理,快速进入内网,开启内网渗透。

注:支持 Pcap 及 socket 两种模式,请根据不同的场合动态切换。

pcap 模式:支持协议识别和漏洞扫描,不支持端口扫描;

socket 模式:支持端口扫描协议识别以及漏洞扫描,扫描速度慢。

Python 实现端口扫描

一、常见端口扫描的原理

0、秘密扫描

秘密扫描是一种不被审计工具所检测的扫描技术。

它通常用于在通过普通的防火墙或路由器的筛选(filtering)时隐藏自己。

秘密扫描能躲避IDS、防火墙、包过滤器和日志审计,从而获取目标端口的开放或关闭的信息。由于没有包含TCP 3次握手协议的任何部分,所以无法被记录下来,比半连接扫描更为隐蔽。

但是这种扫描的缺点是扫描结果的不可靠性会增加,而且扫描主机也需要自己构造IP包。现有的秘密扫描有TCP FIN扫描、TCP ACK扫描、NULL扫描、XMAS扫描和SYN/ACK扫描等。

1、Connect()扫描

此扫描试图与每一个TCP端口进行“三次握手”通信。如果能够成功建立接连,则证明端口开发,否则为关闭。准确度很高,但是最容易被防火墙和IDS检测到,并且在目标主机的日志中会记录大量的连接请求以及错误信息。

TCP connect端口扫描服务端与客户端建立连接成功(目标端口开放)的过程:

① Client端发送SYN;

② Server端返回SYN/ACK,表明端口开放;

③ Client端返回ACK,表明连接已建立;

④ Client端主动断开连接。

建立连接成功(目标端口开放)

TCP connect端口扫描服务端与客户端未建立连接成功(目标端口关闭)过程:

① Client端发送SYN;

② Server端返回RST/ACK,表明端口未开放。

优点:实现简单,对操作者的权限没有严格要求(有些类型的端口扫描需要操作者具有root权限),系统中的任何用户都有权力使用这个调用,而且如果想要得到从目标端口返回banners信息,也只能采用这一方法。

另一优点是扫描速度快。如果对每个目标端口以线性的方式,使用单独的connect()调用,可以通过同时打开多个套接字,从而加速扫描。

缺点:是会在目标主机的日志记录中留下痕迹,易被发现,并且数据包会被过滤掉。目标主机的logs文件会显示一连串的连接和连接出错的服务信息,并且能很快地使它关闭。

2、SYN扫描

扫描器向目标主机的一个端口发送请求连接的SYN包,扫描器在收到SYN/ACK后,不是发送的ACK应答而是发送RST包请求断开连接。这样,三次握手就没有完成,无法建立正常的TCP连接,因此,这次扫描就不会被记录到系统日志中。这种扫描技术一般不会在目标主机上留下扫描痕迹。但是,这种扫描需要有root权限。

·端口开放:(1)Client发送SYN;(2)Server端发送SYN/ACK;(3)Client发送RST断开(只需要前两步就可以判断端口开放)

·端口关闭:(1)Client发送SYN;(2)Server端回复RST(表示端口关闭)

优点:SYN扫描要比TCP Connect()扫描隐蔽一些,SYN仅仅需要发送初始的SYN数据包给目标主机,如果端口开放,则相应SYN-ACK数据包;如果关闭,则响应RST数据包;

3、NULL扫描

反向扫描—-原理是将一个没有设置任何标志位的数据包发送给TCP端口,在正常的通信中至少要设置一个标志位,根据FRC 793的要求,在端口关闭的情况下,若收到一个没有设置标志位的数据字段,那么主机应该舍弃这个分段,并发送一个RST数据包,否则不会响应发起扫描的客户端计算机。也就是说,如果TCP端口处于关闭则响应一个RST数据包,若处于开放则无相应。但是应该知道理由NULL扫描要求所有的主机都符合RFC 793规定,但是windows系统主机不遵从RFC 793标准,且只要收到没有设置任何标志位的数据包时,不管端口是处于开放还是关闭都响应一个RST数据包。但是基于Unix(*nix,如Linux)遵从RFC 793标准,所以可以用NULL扫描。 经过上面的分析,我们知道NULL可以辨别某台主机运行的操作系统是什么操作系统。

端口开放:Client发送Null,server没有响应

端口关闭:(1)Client发送NUll;(2)Server回复RST

说明:Null扫描和前面的TCP Connect()和SYN的判断条件正好相反。在前两种扫描中,有响应数据包的表示端口开放,但在NUll扫描中,收到响应数据包表示端口关闭。反向扫描比前两种隐蔽性高些,当精确度也相对低一些。

用途:判断是否为Windows系统还是Linux。

4、FIN扫描

与NULL有点类似,只是FIN为指示TCP会话结束,在FIN扫描中一个设置了FIN位的数据包被发送后,若响应RST数据包,则表示端口关闭,没有响应则表示开放。此类扫描同样不能准确判断windows系统上端口开发情况。

·端口开放:发送FIN,没有响应

·端口关闭:(1)发送FIN;(2)回复RST

5、ACK扫描

扫描主机向目标主机发送ACK数据包。根据返回的RST数据包有两种方法可以得到端口的信息。方法一是: 若返回的RST数据包的TTL值小于或等于64,则端口开放,反之端口关闭。

6、Xmas-Tree扫描

通过发送带有下列标志位的tcp数据包。

·URG:指示数据时紧急数据,应立即处理。

·PSH:强制将数据压入缓冲区。

·FIN:在结束TCP会话时使用。

正常情况下,三个标志位不能被同时设置,但在此种扫描中可以用来判断哪些端口关闭还是开放,与上面的反向扫描情况相同,依然不能判断windows平台上的端口。

·端口开放:发送URG/PSH/FIN,没有响应

·端口关闭:(1)发送URG/PSH/FIN,没有响应;(2)响应RST

XMAS扫描原理和NULL扫描的类似,将TCP数据包中的ACK、FIN、RST、SYN、URG、PSH标志位置1后发送给目标主机。在目标端口开放的情况下,目标主机将不返回任何信息。

7、Dump扫描

也被称为Idle扫描或反向扫描,在扫描主机时应用了第三方僵尸计算机扫描。由僵尸主机向目标主机发送SYN包。目标主机端口开发时回应SYN|ACK,关闭时返回RST,僵尸主机对SYN|ACK回应RST,对RST不做回应。从僵尸主机上进行扫描时,进行的是一个从本地计算机到僵尸主机的、连续的ping操作。查看僵尸主机返回的Echo响应的ID字段,能确定目标主机上哪些端口是开放的还是关闭的。

二、Python 代码实现

1、利用Python的Socket包中的connect方法,直接对目标IP和端口进行连接并且尝试返回结果,而无需自己构建SYN包。

2、对IP端口进行多线程扫描,注意的是不同的电脑不同的CPU每次最多创建的线程是不一样的,如果创建过多可能会报错,需要根据自己电脑情况修改每次扫描的个数或者将seelp的时间加长都可以。

看完了吗?感觉动手操作一下把!

python学习网,免费的在线学习python平台,欢迎关注!

本文转自:

mac上怎么连接到socket

一、建立socket链接,Mac端终端使用nc命令做端口监听,oc作为客户端建立socket连接。

使用的工具及使用方法:

nc/netcat(选项)(参数)

-g网关:设置路由器跃程通信网关,最多设置8个;

-G指向器数目:设置来源路由指向器,其数值为4的倍数;

-h:在线帮助;

-i延迟秒数:设置时间间隔,以便传送信息及扫描通信端口;

-l:使用监听模式,监控传入的资料;

-n:直接使用ip地址,而不通过域名服务器;

-o输出文件:指定文件名称,把往来传输的数据以16进制字码倾倒成该文件保存;

-p通信端口:设置本地主机使用的通信端口;

-r:指定源端口和目的端口都进行随机的选择;

-s来源位址:设置本地主机送出数据包的IP地址;

-u:使用UDP传输协议;

-v:显示指令执行过程;

-w超时秒数:设置等待连线的时间;

-z:使用0输入/输出模式,只在扫描通信端口时使用。

1、服务端 端口监听

nc -l 6666

2、永久监听TCP端口

nc -lk port

3、临时监听UDP

nc -lu port

4、永久监听UDP

nc -luk port

5、连接服务端

nc -v 127.0.0.1 666

6、端口扫描

nc -v -w 1 127.0.0.1 -z 1-1000

客户端代码:

#import "ViewController.h"

#import sys/socket.h

#import arpa/inet.h//inet_addr

#define connect_host @"127.0.0.1"

#define connect_port 6666

@interface ViewController (){

int clientSocket;

dispatch_queue_t queSerial;

}

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

//button

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

button.frame = CGRectMake((self.view.frame.size.width-200)/2, 100, 200, 30);

button.backgroundColor = [UIColor grayColor];

[button setTitle:@"发送普通文本" forState:UIControlStateNormal];

[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:button];

button = [UIButton buttonWithType:UIButtonTypeCustom];

button.frame = CGRectMake((self.view.frame.size.width-200)/2, 150, 200, 30);

button.backgroundColor = [UIColor grayColor];

[button setTitle:@"发送图片" forState:UIControlStateNormal];

[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:button];

button = [UIButton buttonWithType:UIButtonTypeCustom];

button.frame = CGRectMake((self.view.frame.size.width-200)/2, 200, 200, 30);

button.backgroundColor = [UIColor grayColor];

[button setTitle:@"发送文本加图片" forState:UIControlStateNormal];

[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:button];

[self initSocket];

}

-(void)btn:(UIButton *)button{

if ([button.titleLabel.text isEqualToString:@"发送普通文本"]) {

[self sendMessage:@"发送普通文本"];

}else if ([button.titleLabel.text isEqualToString:@"发送图片"]) {

UIImage *image = [UIImage imageNamed:@"hibo"];

NSData *data = UIImagePNGRepresentation(image);

NSLog(@"height:%f",image.size.height);

NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

NSLog(@"%@",dataString);

// [self sendMessage:dataString];

}else if ([button.titleLabel.text isEqualToString:@"发送文本加图片"]) {

}

}

//发起socket连接

-(BOOL)initSocket{

/*

第一个参数:adress_family,协议簇 AF_INET:IPV4

第二个参数:数据格式-SOCK_STREAM(TCP)/SOCK_DGRAM(UDP)

第三个参数:protocal IPPROTO_TCP,如果为0会根据第二个参数选择合适的协议

返回值:0成功 -1失败

*/

clientSocket = socket(AF_INET, SOCK_STREAM, 0);

NSLog(@"clientsocket:%d",clientSocket);

if (clientSocket0) {

NSLog(@"socket create success");

}else{

NSLog(@"socket create error");

}

/*

连接

第一个参数:客户端socket

第二个参数:指向数据结构,socketAddr的指针,其中包括目的端口和IP地址

第三个参数:结构体数据长度

返回值:0成功 其他错误

*/

struct sockaddr_in addr4 = {0};

addr4.sin_family = AF_INET;//ipv4

addr4.sin_len = sizeof(addr4);

addr4.sin_addr.s_addr = inet_addr(connect_host.UTF8String);

addr4.sin_port = htons(connect_port);//是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为高位字节存放在内存的低地址处

int flag = connect(clientSocket, (const struct sockaddr *)addr4, sizeof(addr4));

if (!flag) {

[self receiveMessage];

}else{

clientSocket = 0;

NSLog(@"连接失败");

}

return flag;

}

//接收消息

-(void)receiveMessage{

if (!queSerial) {

queSerial=dispatch_queue_create("jrQueueSerial", DISPATCH_QUEUE_SERIAL);

}

dispatch_async(queSerial, ^{

uint8_t buffer[1024];

ssize_t recvLen = recv(self-clientSocket, buffer, sizeof(buffer), 0);

NSData *data = [NSData dataWithBytes:buffer length:recvLen];

NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

if (recvLen0) {

NSLog(@"%@:%@",str,[NSThread currentThread]);

NSLog(@"%@",str);

[self receiveMessage];

}else{

NSLog(@"连接断开");

self-clientSocket = 0;

}

});

}

//发送消息

-(BOOL)sendMessage:(NSString *)message{

if (clientSocket==0) {

BOOL flag = [self initSocket];

if (!flag)return NO;

}

ssize_t sendLen = send(clientSocket, message.UTF8String, strlen(message.UTF8String), 0);

NSLog(@"发送消息长度:%zd",sendLen);

return sendLen=0;

}

@end

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

1、在终端执行命令监听端口6666:

nc -l 127.0.0.1 6666

1

1

进入等待连接状态。

2、执行以上oc代码进行socket连接:

client_socket.png

3、以上连接成功,由服务端发送一条消息,客户端接收打印如下:

client_receive.png

注:以上代码中图片发送及文本+图片发送未完成。

二、oc模拟服务端代替Mac终端命令,一步步实现服务端的三次握手及通信。主要使用方法:

1、创建一个socket:

socket(AF_INET, SOCK_STREAM, 0);

1

1

第一个参数:address_family,协议簇 AF_INET对应的IPV4;

第二个参数:数据格式可选两种SOCK_STREAM(TCP)、SOCK_DGRAM(UDP);

第三个参数:protocal IPPROTO_TCP,设置为0会根据第二个参数选择相应的协议;

返回值:sockaddr -1失败 其他成功为socket标号1、2、3、 4,指示为当前socket。

2、端口绑定:

bind(sockaddr, (const struct sockaddr *)addr4, sizeof(addr4));

1

1

第一个参数:创建的socket描述号;

第二个参数:对应socketaddr_in(对应IPV4)的结构体包含了端口号;

第三个参数:socketaddr_in结构体长度。

3、监听端口:

listen(sockaddr, 5);

1

1

第一个参数:创建的socket标号;

第二个参数:可以排队的最大连接个数。

4、获取连接的socket标号和以上使用的标号不同

accept(sockaddr, (struct sockaddr *)aptsockaddr, addrLen);

1

1

第一个参数:创建的socket描述号;

第二个参数:可以排队的最大连接个数;

返回值:接收后的socket标号。

5、接收客户端消息:

recv(aptsocket, buffer, len, 0);

1

1

第一个参数:accept返回的标号理解为当前socket;

第二个参数:接收字符的缓存变量;

第三个参数:一般设置0;

返回值:接收到的数据长度。

6、发送消息:

send(aptsocket, message.UTF8String, strlen(message.UTF8String), 0);

1

1

第一个参数:accept返回的标号理解为当前socket;

第二个参数:发送的消息字符char *型数据;

第三个参数:一般设置0;

返回值:发送的数据长度。

服务端代码:

/*

ipv6

struct sockaddr_in6 addr6 = {0};

bzero(addr6, sizeof(addr6));

addr6.sin6_len = sizeof(addr6);

addr6.sin6_family = AF_INET6;

addr6.sin6_port = htons(connect_port);

htons将主机的无符号短整形数转换成网络字节顺序

htonl将主机的无符号长整形数转换成网络字节顺序

*/

#import "ViewController.h"

#import sys/socket.h

#import arpa/inet.h//inet_addr

#define connect_host @"127.0.0.1"

#define connect_port 6666

@interface ViewController ()

{

int sockaddr;//创建的socket地址

int aptsocket;//同意后返回的socket地址

dispatch_queue_t queSerial;//接收消息的队列

BOOL socket_flag;//socket标识

}

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

//button

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

button.frame = CGRectMake((self.view.frame.size.width-200)/2, 100, 200, 30);

button.backgroundColor = [UIColor grayColor];

[button setTitle:@"回复文本" forState:UIControlStateNormal];

[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:button];

button = [UIButton buttonWithType:UIButtonTypeCustom];

button.frame = CGRectMake((self.view.frame.size.width-200)/2, 150, 200, 30);

button.backgroundColor = [UIColor grayColor];

[button setTitle:@"关闭链接" forState:UIControlStateNormal];

[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:button];

button = [UIButton buttonWithType:UIButtonTypeCustom];

button.frame = CGRectMake((self.view.frame.size.width-200)/2, 200, 200, 30);

button.backgroundColor = [UIColor grayColor];

[button setTitle:@"创建链接" forState:UIControlStateNormal];

[button addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:button];

//创建服务端socket

[self initServerSocket];

}

-(void)btn:(UIButton *)button{

if ([button.titleLabel.text isEqualToString:@"回复文本"]) {

[self sendMessage:@"回复:你好啊!!"];

}else if ([button.titleLabel.text isEqualToString:@"关闭链接"]) {

[self closeSocket];

}else if ([button.titleLabel.text isEqualToString:@"创建链接"]) {

[self initServerSocket];

}

}

//初始化socket

-(BOOL)initServerSocket{

socket_flag = YES;

//1、创建一个socket

sockaddr = socket(AF_INET, SOCK_STREAM, 0);

NSLog(@"sockaddr:%d",sockaddr);

if (sockaddr==-1) {

NSLog(@"创建失败");

return NO;

}

//ipv4

struct sockaddr_in addr4 = {0};

//参数说明:s 要置零的数据的起始地址; n 要置零的数据字节个数。

memset(addr4, 0, sizeof(addr4));

addr4.sin_len = sizeof(addr4);

addr4.sin_family = AF_INET;

addr4.sin_port = htons(connect_port);//将主机的无符号短整形数转换成网络字节顺序

addr4.sin_addr.s_addr = INADDR_ANY;//就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”

//2、端口绑定

int error = bind(sockaddr, (const struct sockaddr *)addr4, sizeof(addr4));

if (error!=0) {

NSLog(@"绑定失败");

return NO;

}

//3、监听端口

error = listen(sockaddr, 5);//开始监听第二个参数可以排队的最大连接个数

if (error!=0) {

NSLog(@"监听失败");

return NO;

}

//4、轮询

if (!queSerial) {

queSerial = dispatch_queue_create("receive_queue", DISPATCH_QUEUE_SERIAL);

}

dispatch_async(queSerial, ^{

[self receiveMessage];

});

return YES;

}

//轮询接收消息

-(void)receiveMessage{

while (true) {

NSLog(@"currentThread:%@",[NSThread currentThread]);

struct sockaddr_in aptsockaddr;

socklen_t addrLen = sizeof(aptsockaddr);

//4、获取连接的socket

aptsocket = accept(sockaddr, (struct sockaddr *)aptsockaddr, addrLen);

NSLog(@"aptsocket:%d",aptsocket);

if (aptsocket != -1) {

NSLog(@"accept success address:%ss, port:%d",inet_ntoa(aptsockaddr.sin_addr),ntohs(aptsockaddr.sin_port));

char buffer[1024];

ssize_t recvLen;

size_t len = sizeof(buffer);

do{

//5、接收客户端的消息

recvLen = recv(aptsocket, buffer, len, 0);

NSString *str = [NSString stringWithCString:buffer encoding:NSUTF8StringEncoding];

NSLog(@"receive:%@",str);

NSLog(@"buffer:%s",buffer);

[self sendMessage:@"回复你:哈哈"];

}while(socket_flag);

}

close(aptsocket);

break;//链接失败后跳出轮询

}

}

//发送消息

-(BOOL)sendMessage:(NSString *)message{

if (sockaddr==0) {

NSLog(@"链接已断开");

}

ssize_t sendLen = send(aptsocket, message.UTF8String, strlen(message.UTF8String), 0);

NSLog(@"发送消息长度:%zd",sendLen);

return sendLen=0;

}

//断开链接

-(void)closeSocket{

NSLog(@"关闭链接");

socket_flag = NO;

}

@end

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

通过以上过程,对socket通信能有一个初步了解,可以利用socket通信搭建一套简单的聊天系统

0条大神的评论

发表评论