我的编程空间,编程开发者的网络收藏夹
学习永远不晚

如何解析Socket和TCP连接过程

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

如何解析Socket和TCP连接过程

如何解析Socket和TCP连接过程,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

一. 背景

1.完整的套接字格式{protocol,class="lazy" data-src_addr,class="lazy" data-src_port,dest_addr,dest_port}。

这常被称为套接字的五元组。其中protocol指定了是TCP还是UDP连接,其余的分别指定了源地址、源端口、目标地址、目标端口。但是这些内容是怎么来的呢?

2.TCP协议栈维护着两个socket缓冲区:send buffer和recv buffer。

要通过TCP连接发送出去的数据都先拷贝到send buffer,可能是从用户空间进程的app buffer拷入的,也可能是从内核的kernel buffer拷入的,拷入的过程是通过send()函数完成的,由于也可以使用write()函数写入数据,所以也把这个过程称为写数据,相应的send buffer也就有了别称write buffer。不过send()函数比write()函数更有效率。

最终数据是通过网卡流出去的,所以send buffer中的数据需要拷贝到网卡中。由于一端是内存,一端是网卡设备,可以直接使用DMA的方式进行拷贝,无需CPU的参与。也就是说,send buffer中的数据通过DMA的方式拷贝到网卡中并通过网络传输给TCP连接的另一端:接收端。

当通过TCP连接接收数据时,数据肯定是先通过网卡流入的,然后同样通过DMA的方式拷贝到recv buffer中,再通过recv()函数将数据从recv buffer拷入到用户空间进程的app buffer中。

3.两种套接字:监听套接字和已连接套接字。

监听套接字是在服务进程读取配置文件时,从配置文件中解析出要监听的地址、端口,然后通过socket()函数创建的,然后再通过bind()函数将这个监听套接字绑定到对应的地址和端口上。随后,进程/线程就可以通过listen()函数来监听这个端口(严格地说是监控这个监听套接字)。

已连接套接字是在监听到TCP连接请求并三次握手后,通过accept()函数返回的套接字,后续进程/线程就可以通过这个已连接套接字和客户端进行TCP通信。

为了区分socket()函数和accept()函数返回的两个套接字描述符,有些人使用listenfd和connfd分别表示监听套接字和已连接套接字,挺形象的,下文偶尔也这么使用。

下面就来说明各种函数的作用,分析这些函数,也是在连接、断开连接的过程。

二. 连接的具体过程分析

2.1 socket()函数

socket()函数的作用就是生成一个用于通信的套接字文件描述符sockfd(socket() creates an endpoint for communication and returns a descriptor)。这个套接字描述符可以作为稍后bind()函数的绑定对象。

2.2 bind()函数

服务程序通过分析配置文件,从中解析出想要监听的地址和端口,再加上可以通过socket()函数生成的套接字sockfd,就可以使用bind()函数将这个套接字绑定到要监听的地址和端口组合"addr:port"上。绑定了端口的套接字可以作为listen()函数的监听对象。

绑定了地址和端口的套接字就有了源地址和源端口(对服务器自身来说是源),再加上通过配置文件中指定的协议类型,五元组中就有了其中3个元组。即:

{protocal,class="lazy" data-src_addr,class="lazy" data-src_port}

但是,常见到有些服务程序可以配置监听多个地址、端口实现多实例。这实际上就是通过多次socket()+bind()系统调用生成并绑定多个套接字实现的。

2.3 listen()函数和connect()函数

顾名思义,listen()函数就是监听已经通过bind()绑定了addr+port的套接字的。监听之后,套接字就从CLOSE状态转变为LISTEN状态,于是这个套接字就可以对外提供TCP连接的窗口了。

而connect()函数则用于向某个已监听的套接字发起连接请求,也就是发起TCP的三次握手过程。从这里可以看出,连接请求方(如客户端)才会使用connect()函数,当然,在发起connect()之前,连接发起方也需要生成一个sockfd,且使用的很可能是绑定了随机端口的套接字。既然connect()函数是向某个套接字发起连接的,自然在使用connect()函数时需要带上连接的目的地,即目标地址和目标端口,这正是服务端的监听套接字上绑定的地址和端口。同时,它还要带上自己的地址和端口,对于服务端来说,这就是连接请求的源地址和源端口。于是,TCP连接的两端的套接字都已经成了五元组的完整格式。

2.3.1 深入分析listen()

再来细说listen()函数。如果监听了多个地址+端口,即需要监听多个套接字,那么此刻负责监听的进程/线程会采用select()、poll()的方式去轮询这些套接字(当然,也可以使用epoll()模式),其实只监控一个套接字时,也是使用这些模式去轮询的,只不过select()或poll()所感兴趣的套接字描述符只有一个而已。

不管使用select()还是poll()模式(至于epoll的不同监控方式就无需多言了),在进程/线程(监听者)监听的过程中,它阻塞在select()或poll()上。直到有数据(SYN信息)写入到它所监听的sockfd中(即recv buffer),监听者被唤醒并将SYN数据拷贝到用户空间中自己管理的app buffer中进行一番处理,并发送SYN+ACK,这个数据同样需要从app buffer中拷入send buffer(使用send()函数)中,再拷入网卡传送出去。这时会在连接未完成队列中为这个连接创建一个新项目,并设置为SYN_RECV状态。然后再次使用select()/poll()方式监控着套接字listenfd,直到再次有数据写入这个listenfd中监听者才被唤醒,如果这次写入的数据是ACK信息,则将数据拷入到app buffer中进行一番处理后,把连接未完成队列中对应的项目移入连接已完成队列,并设置为ESTABLISHED状态,如果这次接收的不是ACK,则肯定是SYN,也就是新的连接请求,于是和上面的处理过程一样,放入连接未完成队列。这就是监听者处理整个TCP连接的循环过程。

也就是说,listen()函数还维护了两个队列:连接未完成队列和连接已完成队列。当监听者接收到某个客户端发来的SYN并回复了SYN+ACK之后,就会在未完成连接队列的尾部创建一个关于这个客户端的条目,并设置它的状态为SYN_RECV。显然,这个条目中必须包含客户端的地址和端口相关信息(可能是hash过的,我不太确定)。当服务端再次收到这个客户端发送的ACK信息之后,监听者线程通过分析数据就知道这个消息是回复给未完成连接队列中的哪一项的,于是将这一项移入到已完成连接队列,并设置它的状态为ESTABLISHED。

当未完成连接队列满了,监听者被阻塞不再接收新的连接请求,并通过select()/poll()等待两个队列触发可写事件。当已完成连接队列满了,则监听者也不会接收新的连接请求,同时,正准备移入到已完成连接队列的动作被阻塞。在Linux 2.2以前,listen()函数有一个backlog的参数,用于设置这两个队列的最大总长度,从Linux 2.2开始,这个参数只表示已完成队列的最大长度,而/proc/sys/net/ipv4/tcp_max_syn_backlog则用于设置未完成队列的最大长度。/proc/sys/net/core/somaxconn则是硬限制已完成队列的最大长度,默认为128,如果backlog大于somaxconn,则backlog会被截断为等于该值。

当连接已完成队列中的某个连接被accept()后,表示TCP连接已经建立完成,这个连接将采用自己的socket buffer和客户端进行数据传输。这个socket buffer和监听套接字的socket buffer都是用来存储TCP收、发的数据,但它们的意义已经不再一样:监听套接字的socket buffer只接受TCP连接请求过程中的syn和ack数据;而已建立的TCP连接的socket buffer主要存储的内容是两端传输的"正式"数据,例如服务端构建的响应数据,客户端发起的Http请求数据。

netstat命令的Send-Q和Recv-Q列表示的就是socket buffer相关的内容,以下是man netstat的解释:
Recv-Q Established: The count of bytes not copied by the user program connected to this socket. Listening: Since Kernel 2.6.18 this column contains the current syn backlog.Send-Q Established: The count of bytes not acknowledged by the remote host. Listening: Since Kernel 2.6.18 this column contains the maximum size of the syn backlog.

对于监听状态的套接字,Recv-Q表示的是当前syn backlog,即已完成队列中当前的连接个数,Send-Q表示的是syn backlog的最大值,即已完成连接队列的最大连接限制个数;

对于已经建立的tcp连接,Recv-Q列表示的是recv buffer中还未被用户进程拷贝走的数据大小,Send-Q列表示的是远程主机还未返回ACK消息的数据大小。之所以区分已建立TCP连接的套接字和监听状态的套接字,就是因为这两种状态的套接字采用不同的socket buffer,其中监听套接字更注重队列的长度,而已建立TCP连接的套接字更注重收、发的数据大小。

[root@xuexi ~]# netstat -tnlActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address           Foreign Address         State      tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     tcp6       0      0 :::80                   :::*                    LISTEN     tcp6       0      0 :::22                   :::*                    LISTEN     tcp6       0      0 ::1:25                  :::*                    LISTEN[root@xuexi ~]# ss -tnlState      Recv-Q Send-Q                    Local Address:Port      Peer Address:PortLISTEN     0      128                                   *:22                   *:*   LISTEN     0      100                           127.0.0.1:25                   *:*   LISTEN     0      128                                  :::80                  :::*   LISTEN     0      128                                  :::22                  :::*   LISTEN     0      100                                 ::1:25                  :::*

注意,Listen状态下的套接字,netstat的Send-Q和ss命令的Send-Q列的值不一样,因为netstat根本就没写上已完成队列的最大长度。因此,判断队列中是否还有空闲位置接收新的tcp连接请求时,应该尽可能地使用ss命令而不是netstat。

2.3.2 syn flood的影响

此外,如果监听者发送SYN+ACK后,迟迟收不到客户端返回的ACK消息,监听者将被select()/poll()设置的超时时间唤醒,并对该客户端重新发送SYN+ACK消息,防止这个消息遗失在茫茫网络中。但是,这一重发就出问题了,如果客户端调用connect()时伪造源地址,那么监听者回复的SYN+ACK消息是一定到不了对方的主机的,也就是说,监听者会迟迟收不到ACK消息,于是重新发送SYN+ACK。但无论是监听者因为select()/poll()设置的超时时间一次次地被唤醒,还是一次次地将数据拷入send buffer,这期间都是需要CPU参与的,而且send buffer中的SYN+ACK还要再拷入网卡(这次是DMA拷贝,不需要CPU)。如果,这个客户端是个攻击者,源源不断地发送了数以千、万计的SYN,监听者几乎直接就崩溃了,网卡也会被阻塞的很严重。这就是所谓的syn flood攻击。

解决syn flood的方法有多种,例如,缩小listen()维护的两个队列的最大长度,减少重发syn+ack的次数,增大重发的时间间隔,减少收到ack的等待超时时间,使用syncookie等,但直接修改tcp选项的任何一种方法都不能很好兼顾性能和效率。所以在连接到达监听者线程之前对数据包进行过滤是极其重要的手段。

2.4 accept()函数

accpet()函数的作用是读取已完成连接队列中的第一项(读完就从队列中移除),并对此项生成一个用于后续连接的套接字描述符,假设使用connfd来表示。有了新的连接套接字,工作进程/线程(称其为工作者)就可以通过这个连接套接字和客户端进行数据传输,而前文所说的监听套接字(sockfd)则仍然被监听者监听。

例如,prefork模式的httpd,每个子进程既是监听者,又是工作者,每个客户端发起连接请求时,子进程在监听时将它接收进来,并释放对监听套接字的监听,使得其他子进程可以去监听这个套接字。多个来回后,终于是通过accpet()函数生成了新的连接套接字,于是这个子进程就可以通过这个套接字专心地和客户端建立交互,当然,中途可能会因为各种io等待而多次被阻塞或睡眠。这种效率真的很低,仅仅考虑从子进程收到SYN消息开始到最后生成新的连接套接字这几个阶段,这个子进程一次又一次地被阻塞。当然,可以将监听套接字设置为非阻塞IO模式,只是即使是非阻塞模式,它也要不断地去检查状态。

再考虑worker/event处理模式,每个子进程中都使用了一个专门的监听线程和N个工作线程。监听线程专门负责监听并建立新的连接套接字描述符,放入apache的套接字队列中。这样监听者和工作者就分开了,在监听的过程中,工作者可以仍然可以自由地工作。如果只从监听这一个角度来说,worker/event模式比prefork模式性能高的不是一点半点。

当监听者发起accept()系统调用的时候,如果已完成连接队列中没有任何数据,那么监听者会被阻塞。当然,可将套接字设置为非阻塞模式,这时accept()在得不到数据时会返回EWOULDBLOCK或EAGAIN的错误。可以使用select()或poll()或epoll来等待已完成连接队列的可读事件。还可以将套接字设置为信号驱动IO模式,让已完成连接队列中新加入的数据通知监听者将数据复制到app buffer中并使用accept()进行处理。

常听到同步连接和异步连接的概念,它们到底是怎么区分的?同步连接的意思是,从监听者监听到某个客户端发送的SYN数据开始,它必须一直等待直到建立连接套接字、并和客户端数据交互结束,在和这个客户端的连接关闭之前,中间不会接收任何其他客户端的连接请求。细致一点解释,那就是同步连接时需要保证socket buffer和app buffer数据保持一致。通常以同步连接的方式处理时,监听者和工作者是同一个进程,例如httpd的prefork模型。而异步连接则可以在建立连接和数据交互的任何一个阶段接收、处理其他连接请求。通常,监听者和工作者不是同一个进程时使用异步连接的方式,例如httpd的event模型,尽管worker模型中监听者和工作者分开了,但是仍采用同步连接,监听者将连接请求接入并创建了连接套接字后,立即交给工作线程,工作线程处理的过程中一直只服务于该客户端直到连接断开,而event模式的异步也仅仅是在工作线程处理特殊的连接(如处于长连接状态的连接)时,可以将它交给监听线程保管而已,对于正常的连接,它仍等价于同步连接的方式,因此httpd的event所谓异步,其实是伪异步。通俗而不严谨地说,同步连接是一个进程/线程处理一个连接,异步连接是一个进程/线程处理多个连接。

2.5 send()和recv()函数

send()函数是将数据从app buffer复制到send buffer中(当然,也可能直接从内核的kernel buffer中复制),recv()函数则是将recv buffer中的数据复制到app buffer中。当然,使用write()和read()函数替代它们并没有什么不可以,只是send()/recv()的针对性更强而已。

这两个函数都涉及到了socket buffer,但是在调用send()或recv()时,复制的源buffer中是否有数据、复制的目标buffer中是否已满而导致不可写是需要考虑的问题。不管哪一方,只要不满足条件,调用send()/recv()时进程/线程会被阻塞(假设套接字设置为阻塞式IO模型)。当然,可以将套接字设置为非阻塞IO模型,这时在buffer不满足条件时调用send()/recv()函数,调用函数的进程/线程将返回错误状态信息EWOULDBLOCK或EAGAIN。buffer中是否有数据、是否已满而导致不可写,其实可以使用select()/poll()/epoll去监控对应的文件描述符(对应socket buffer则监控该socket描述符),当满足条件时,再去调用send()/recv()就可以正常操作了。还可以将套接字设置为信号驱动IO或异步IO模型,这样数据准备好、复制好之前就不用再做无用功去调用send()/recv()了。

2.6 close()、shutdown()函数

通用的close()函数可以关闭一个文件描述符,当然也包括面向连接的网络套接字描述符。当调用close()时,将会尝试发送send buffer中的所有数据。但是close()函数只是将这个套接字引用计数减1,就像rm一样,删除一个文件时只是移除一个硬链接数,只有这个套接字的所有引用计数都被删除,套接字描述符才会真的被关闭,才会开始后续的四次挥手中。对于父子进程共享套接字的并发服务程序,调用close()关闭子进程的套接字并不会真的关闭套接字,因为父进程的套接字还处于打开状态,如果父进程一直不调用close()函数,那么这个套接字将一直处于打开状态,见一直进入不了四次挥手过程。

而shutdown()函数专门用于关闭网络套接字的连接,和close()对引用计数减一不同的是,它直接掐断套接字的所有连接,从而引发四次挥手的过程。可以指定3种关闭方式:

1.关闭写。此时将无法向send buffer中再写数据,send buffer中已有的数据会一直发送直到完毕。

2.关闭读。此时将无法从recv buffer中再读数据,recv buffer中已有的数据只能被丢弃。

3.关闭读和写。此时无法读、无法写,send buffer中已有的数据会发送直到完毕,但recv buffer中已有的数据将被丢弃。

无论是shutdown()还是close(),每次调用它们,在真正进入四次挥手的过程中,它们都会发送一个FIN。

三. 地址/端口重用技术

正常情况下,一个addr+port只能被一个套接字绑定,换句话说,addr+port不能被重用,不同套接字只能绑定到不同的addr+port上。举个例子,如果想要开启两个sshd实例,先后启动的sshd实例配置文件中,必须不能配置同样的addr+port。同理,配置web虚拟主机时,除非是基于域名,否则两个虚拟主机必须不能配置同一个addr+port,而基于域名的虚拟主机能绑定同一个addr+port的原因是http的请求报文中包含主机名信息,实际上在这类连接请求到达的时候,仍是通过同一个套接字进行监听的,只不过监听到之后,httpd的工作进程/线程可以将这个连接分配到对应的主机上。

既然上面说的是正常情况下,当然就有非正常情况,也就是地址重用和端口重用技术,组合起来就是套接字重用。在现在的Linux内核中,已经有支持地址重用的socket选项SO_REUSEADDR和支持端口重用的socket选项SO_REUSEPORT。设置了端口重用选项后,再去绑定套接字,就不会再有错误了。而且,一个实例绑定了两个addr+port之后(可以绑定多个,此处以两个为例),就可以同一时刻使用两个监听进程/线程分别去监听它们,客户端发来的连接也就可以通过round-robin的均衡算流地被接待。

对于监听进程/线程来说,每次重用的套接字被称为监听桶(listener bucket),即每个监听套接字都是一个监听桶。

以httpd的worker或event模型为例,假设目前有3个子进程,每个子进程中都有一个监听线程和N个工作线程。

那么,在没有地址重用的情况下,各个监听线程是争抢式监听的。在某一时刻,这个监听套接字上只能有一个监听线程在监听(通过获取互斥锁mutex方式获取监听资格),当这个监听线程接收到请求后,让出监听的资格,于是其他监听线程去抢这个监听资格,并只有一个线程可以抢的到。
当使用了地址重用和端口重用技术,就可以为同一个addr+port绑定多个套接字。例如下图中是多使用一个监听桶时,有两个套接字,于是有两个监听线程可以同时进行监听,当某个监听线程接收到请求后,让出资格,让其他监听线程去争抢资格。
如果再多绑定一个套接字,那么这三个监听线程都不用让出监听资格,可以无限监听。
似乎感觉上去,性能很好,不仅减轻了监听资格(互斥锁)的争抢,避免"饥饿问题",还能更高效地监听,并因为可以负载均衡,从而可以减轻监听线程的压力。但实际上,每个监听线程的监听过程都是需要消耗CPU的,如果只有一核CPU,即使重用了也体现不出重用的优势,反而因为切换监听线程而降低性能。因此,要使用端口重用,必须考虑是否已将各监听进程/线程隔离在各自的cpu中,也就是说是否重用、重用几次都需考虑cpu的核数以及是否将进程与cpu相互绑定。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网行业资讯频道,感谢您对编程网的支持。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

如何解析Socket和TCP连接过程

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何解析Socket和TCP连接过程

如何解析Socket和TCP连接过程,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。一. 背景1.完整的套接字格式{protocol,src_addr,src_p
2023-06-03

python如何使用socket实现TCP协议长连接框架

这篇文章主要介绍了python如何使用socket实现TCP协议长连接框架,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。分析多了协议就会发现,很多的应用,特别是游戏类和IM类
2023-06-29

php socket无法连接如何解决

今天小编给大家分享一下php socket无法连接如何解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。php socket
2023-07-04

如何强制 MySQL 通过 TCP 而不是 Unix 套接字连接?

使用 MySQL 客户端库的 mysql 和 mysqldump 等程序支持通过多种传输协议(如 TCP/IP、Unix 套接字)连接 MySQL 到服务器文件、命名管道、共享内存等。对于给定的连接,如果未指定传输协议,则将其确定为单独的任
2023-10-22

如何解决TCP半开连接数限制问题

这期内容当中小编将会给大家带来有关如何解决TCP半开连接数限制问题,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。禁用Vista/Win7中的TCP半开连接数限制   步骤如下,适用于Windows Vis
2023-06-14

timewait连接过多如何解决

解决timewait连接过多的问题,可以采取以下方法:1. 调整系统参数:通过调整操作系统的网络参数可以减少timewait连接数量。可以增加系统的最大文件句柄数(File Descriptor)和最大连接数(Maximum Connect
2023-09-07

socket连接成功收不到消息如何解决

如果socket连接成功但无法接收消息,可能有以下几种原因及解决方法:1. 网络问题:检查网络连接是否正常,可以尝试重新连接或者更换网络环境。2. 服务器问题:确保服务器端正常运行,并且能够发送消息给客户端。可以尝试连接其他服务器进行测试。
2023-09-12

redis连接数过高如何解决

调整Redis配置参数:可以通过调整Redis的最大连接数限制来减少连接数过高的问题。可以通过修改Redis的配置文件redis.conf中的参数maxclients来设置最大连接数限制。使用连接池:可以使用连接池来管理Redis连接,减少
redis连接数过高如何解决
2024-03-15

kafka连接数过多如何解决

当Kafka连接数过多时,可以采取以下措施来解决问题:1. 调整Kafka的最大连接数限制:修改Kafka的配置文件,增加`max.connections`参数的值,以增加Kafka允许的最大连接数。2. 增加Kafka集群的容量:如果Ka
2023-09-14

如何测试Linux下tcp最大连接数限制详解

前言 关于TCP服务器最大并发连接数有一种误解就是“因为端口号上限为65535,所以TCP服务器理论上的可承载的最大并发连接数也是65535”。 先说结论:对于TCP服务端进程来说,他可以同时连接的客户端数量并不受限于可用端口号。并发连接数
2022-06-04

MySQL如何通过Navicat实现远程连接

直接使用Navicat通过IP连接会报各种错误,例如:Error 1130: Host '192.168.1.80' is not allowed to connect to this MySQL server。 经过个人验证,得到解决方法
2022-05-18

win10远程连接win7连接不上如何解决

这篇文章主要介绍“win10远程连接win7连接不上如何解决”,在日常操作中,相信很多人在win10远程连接win7连接不上如何解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”win10远程连接win7连接
2023-07-01

如何解决MySQL报错:连接数过多

要解决MySQL报错连接数过多,可以尝试以下几种方法:1. 增加最大连接数:可以通过修改MySQL配置文件中的max_connections参数来增加最大连接数。找到my.cnf或my.ini文件(路径可能位于/etc/mysql/my.c
2023-10-20

Can't connect to local MySQL server through socket 'socket_name' (111) - 如何解决MySQL报错:无法通过套接字连接到本地MyS

在开发过程中,我们经常会遇到与数据库连接相关的问题。其中一个常见的问题是MySQL报错:“Can't connect to local MySQL server through socket 'socket_name' (111)”。这个错
2023-10-21

如何解析Flex应用程序连接数据的实现

如何解析Flex应用程序连接数据的实现,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。因为Flex应用程序并不直接与一个数据库进行连接,所以你需要使用某种类型的服
2023-06-17

Android Socket 线程连接openwrt与arduino单片机串口双向通信的实例解析

废话不多说了,直接给大家贴代码了,具体代码如下所示:package zcd.netanything; import java.io.BufferedReader; import java.io.InputStreamReader; impo
2022-06-06

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录