LinuxTCP服务器:构建高效稳定的网络通信(tcpserverlinux)

在今天的互联网时代,网络通信已经成为了各种应用程序中不可或缺的一部分。而TCP协议则是现代网络通信的主要标准之一,它为不同的应用程序提供了高效、可靠的数据传输服务。因此,为了构建一个高效稳定的网络通信系统,我们需要学习如何构建一个优秀的TCP服务器。

在本文中,我们将会讨论一些关于构建Linux TCP服务器的基本知识和技能,包括如何设置和优化服务器,如何使用多线程、多进程、I/O多路复用和异步I/O等技术,以此为基础手动构建出高效稳定的TCP服务器。

之一步:服务器的配置

构建一个高效稳定的TCP服务器需要首先对服务器进行配置。服务器的配置包括设置和优化TCP参数以及优化操作系统的配置。在这一步,我们将会了解一些最基本的TCP参数和操作系统配置项的设置,以保证服务器能够具有更佳的性能表现。

TCP参数设置

TCP参数是影响服务器性能的最重要的因素之一。其中最基本的参数包括TCP窗口大小、MSS等。下面是一些常见的TCP参数设置:

1. TCP窗口大小

TCP窗口大小是指数据量的一种计算方式,在TCP连接的初始化过程中会进行设置。而TCP窗口大小的设置会直接影响到服务器的性能表现。在Linux系统上,可以通过修改sysctl.conf文件中的net.core.wmem_max、net.core.rmem_max、net.ipv4.tcp_wmem和net.ipv4.tcp_rmem等参数进行优化,以提高TCP窗口大小。

2. Nagle算法

Nagle算法是用于优化TCP网络通信的一个重要算法。在默认情况下,Nagle算法会将应用程序发送的小数据包合并为一个更大的数据包再进行发送,以减少网络通信的次数。但在对于实时性要求较高的应用中,可以关闭Nagle算法来提高TCP网络通信的速度。

操作系统配置项设置

操作系统的配置项设置是构建高效稳定的TCP服务器的另一个重要组成部分。在本文中,我们将会介绍一些常见的操作系统配置项,以提高服务器的性能表现。

1. 使用最新的内核

使用最新的内核可以获取到所有最新的性能改进和优化。因此,我们建议使用最新的操作系统版本,以保证服务器的性能表现。

2. 关闭不必要的服务

在服务器运行时,关闭不必要的进程和服务可以显著提高服务器性能。因此,在构建高效稳定的TCP服务器时,我们应该关闭所有不必要的服务和进程,从而保证服务器的稳定运行。

第二步:使用多进程和多线程技术

在现代操作系统中,多进程和多线程可以帮助服务器使用不同的CPU核心,提高服务器的性能。在使用多线程和多进程技术时,我们需要注意以下几点:

1. 在使用多线程技术时,需要注意线程安全问题。

2. 在使用多进程技术时,需要注意进程通信问题。

3. 在使用多线程和多进程技术时,需要合理使用CPU核心,避免CPU资源的浪费。

第三步:使用I/O多路复用和异步I/O技术

I/O多路复用和异步I/O技术是构建高效稳定的TCP服务器的另一个重要组成部分。这些技术可以帮助服务器在处理多个网络请求时提高效率,从而更快地响应客户端请求。

在使用I/O多路复用和异步I/O技术时,需要注意以下几点:

1. 在使用I/O多路复用技术时,需要注意同时处理多个I/O事件时的问题,防止出现死锁等情况。

2. 在使用异步I/O技术时,需要注意I/O事件发生的顺序,以避免出现数据错误等不良情况。

结论

Linux TCP服务器是构建高效稳定的网络通信的一个关键部分。在本文中,我们介绍了一些关于如何构建高效稳定的TCP服务器的基本知识和技能。在实际的应用中,我们应该针对不同的应用场景制定不同的优化策略,以保证服务器的更佳性能表现。

相关问题拓展阅读:

  • linux python connect 对同一个端口可以建立多少个
  • Linux下 client server 连不上

linux python connect 对同一个端口可以建立多少个

如果是tcp client用同一个本地端口去连不同的两个服务器ip,连第二个时就会提示端口已被占用。但服务器的监听端口,可以accept多次,建立多个socket;我的问题是服务器一个端口为什么能建立多个连败樱接而客户端却不行呢?

TCP server 可以,TCP client 也可以。一个套接字只能建立一个连接,无论对于 server 还是 client。

注意报错消息是:

(EISCONN) Transport endpoint is already connected

man 2 connect 说得很清楚了:

Generally, connection-based protocol sockets may successfully connect() only once; connectionless protocol sockets may use connect() multiple times to change their association.

就是说,TCP 套接字最多只能调用 connect 一次。那么,你的监听套接字调用 connect 了几次?

来点有意思的。

一个套接字不能连接两次,并不代表一个本地地址不能用两次,看!****加粗文字**加做并粗文字**

>>> import socket

>>> s = socket.socket()

# since Linux 3.9, 见 man 7 socket

>>> s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

>>> s2 = socket.socket()

>>> s2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

>>> s.bind((‘127.0.0.1’, 12345))

>>> s2.bind((‘127.0.0.1’, 12345))

# 都可以使用同一本地地址来连接哦

>>> s.connect((‘127.0.0.1’, 80))

>>> s2.connect((‘127.0.0.1’, 4321))

>>> netstat -npt | grep 12345

(Not all processes could be identified, non-owned process info

will not be shown, you would have to be root to see it all.)

tcp 0 127.0.0.1:127.0.0.1:ESTABLISHED 18284/python3

tcp 0 127.0.0.1:127.0.0.1:ESTABLISHED 4568/python3

tcp 0 127.0.0.1:127.0.0.1:ESTABLISHED –

tcp 0 127.0.0.1:127.0.0.1:ESTABLISHED 4568/python3

你们这些有女友的都弱爆了啦

更新:大家来玩 TCP: 一个人也可以建立 TCP 连接呢 – 依云’s Blog

2023年08月19日回答 · 2023年08月19日更新

依云21.1k 声望

答案对人有帮助,有参考价值1答案没帮助,是错误的答案,答非所问

内核是以一个(著名的)5元信息组来标识不同的socket的:源地址、源端口、目的地址、目的端口、协议号。任何一个不同,都不叫“同一个socket”。

2023年08月20日回答

sched_yield80 声望

答案对人有帮察胡丛助,有参考价值0答案没帮助,是错误的答案,答非所问

首先,TCP链接是可靠的端对端的链接,每个TCP链接由4个要素组成:2组IP地址(本地和远端),2组端口地址(本地和远端)。其中如果需要跟端口信息绑定时,都需要调用bind函数,如果server端针对2个同样的IP、端口组进行同样的绑定时,第2次同样是不成功的。

2023年08月16日回答

charliecui2.4k 声望

答案对人有帮助,有参考价值0答案没帮助,是错误的答案,答非所问

有个相关的问题: ftp的数据传输,服务器会用20端口主动连接客户端,如果两个客户端同时在一下载东西,那ftp 服务器能用20端口去连接两个ip ?(这时ftp的服务器其实是tcp里的客户端)

2023年08月16日回答

编辑

hyanleo163 声望

+1

能啊,看我的实验。

依云 · 2023年08月19日

不管是服务器还是客户端,建立TCP链接,同一个端口都只能使用一次。

这句话其实是**错的**!

对于TCP协议,要成功建立一个新的链接,需要保证新链接四个要素组合体的唯一性:客户端的IP、客户端的port、服务器端的IP、服务器端的port。也就是说,服务器端的同一个IP和port,可以和同一个客户端的多个不同端口成功建立多个TCP链接(与多个不同的客户端当然也可以),只要保证【Server IP + Server Port + Client IP + Client Port】这个组合唯一不重复即可。

> netstat -a -n -p tcp |grep 9999

tcp.0.0.1:.0.0.1:9999 ESTABLISHED 2701/nc

tcp.0.0.1:.0.0.1:9999 ESTABLISHED 2752/nc

上述结果127.0.0.1:9999中9999端口成功建立两个TCP链接,也就可以理解。

**客户端**发送TCP链接请求的端口,也就是后续建立TCP链接使用的端口,所以一旦TCP链接建立,端口就被占用,无法再建立第二个链接。

而**服务器端**有两类端口:侦听端口 和 后续建立TCP链接的端口。其中侦听端口只负责侦听客户端发送来的TCP链接请求,不用作建立TCP链接使用,一旦侦听到有客户端发送TCP链接请求,就分配一个端口(一般随机分配,且不会重复)用于建立TCP链接,而不是所说的服务器一个端口能建立多个连接。

上述描述也比较片面,客户端如何请求及建立链接,服务器端如何侦听及是否分配新随机端口等…应该都可以在应用层面进行控制,所以上述描述可以作为建立TCP链接的一种方式,仅供参考。

一些英文的参考:

How do multiple clients connect simultaneously to one port, say 80, on a server?

TCP : two different sockets sharing a port?

提升linux下tcp服务器并发连接数限制:30:23

1、修改用户进程可打开文件数限制

在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,更高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。可使用ulimit命令查看系统允许当前用户进程打开的文件数限制:

$ ulimit -n

这表示当前用户的每个进程最多允许同时打开1024个文件,这1024个文件中还得除去每个进程必然打开的标准输入,标准输出,标准错误,服务器监听 socket,进程间通讯的unix域socket等文件,那么剩下的可用于客户端socket连接的文件数就只有大概=1014个左右。也就是说缺省情况下,基于Linux的通讯程序最多允许同时1014个TCP并发连接。

对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的进程同时打开的文件数量的软限制(soft limit)和硬限制(hardlimit)。其中软限制是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数;硬限制则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。通常软限制小于或等于硬限制。

修改上述限制的最简单的办法就是使用ulimit命令:

$ ulimit -n

上述命令中,在中指定要设置的单一进程允许打开的更大文件数。如果系统回显类似于“Operation notpermitted”之类的话,说明上述限制修改失败,实际上是因为在中指定的数值超过了Linux系统对该用户打开文件数的软限制或硬限制。因此,就需要修改Linux系统对用户的关于打开文件数的软限制和硬限制。

之一步,修改/etc/security/limits.conf文件,在文件中添加如下行:

speng soft nofile 10240

speng hard nofile 10240

其中speng指定了要修改哪个用户的打开文件数限制,可用’*’号表示修改所有用户的限制;soft或hard指定要修改软限制还是硬限制;10240则指定了想要修改的新的限制值,即更大打开文件数(请注意软限制值要小于或等于硬限制)。修改完后保存文件。

第二步,修改/etc/pam.d/login文件,在文件中添加如下行:

session required /lib/security/pam_limits.so

这是告诉Linux在用户完成系统登录后,应该调用pam_limits.so模块来设置系统对该用户可使用的各种资源数量的更大限制(包括用户可打开的更大文件数限制),而pam_limits.so模块就会从/etc/security/limits.conf文件中读取配置来设置这些限制值。修改完后保存此文件。

第三步,查看Linux系统级的更大打开文件数限制,使用如下命令:

$ cat /proc/sys/fs/file-max

这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)12158个文件,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的更佳的更大同时打开文件数限制,如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。修改此硬限制的方法是修改/etc/rc.local脚本,在脚本中添加如下行:

echo> /proc/sys/fs/file-max

这是让Linux在启动完成后强行将系统级打开文件数硬限制设置为22158。修改完后保存此文件。

完成上述步骤后重启系统,一般情况下就可以将Linux系统对指定用户的单一进程允许同时打开的更大文件数限制设为指定的数值。如果重启后用 ulimit- n命令查看用户可打开文件数限制仍然低于上述步骤中设置的更大值,这可能是因为在用户登录脚本/etc/profile中使用ulimit-n命令已经将用户可同时打开的文件数做了限制。由于通过ulimit-n修改系统对用户可同时打开文件的更大数限制时,新修改的值只能小于或等于上次ulimit-n 设置的值,因此想用此命令增大这个限制值是不可能的。所以,如果有上述问题存在,就只能去打开/etc/profile脚本文件,在文件中查找是否使用了 ulimit-n限制了用户可同时打开的更大文件数量,如果找到,则删除这行命令,或者将其设置的值改为合适的值,然后保存文件,用户退出并重新登录系统即可。

通过上述步骤,就为支持高并发TCP连接处理的通讯处理程序解除关于打开文件数量方面的系统限制。

2、修改网络内核对TCP连接的有关限制

在Linux上编写支持高并发TCP连接的客户端通讯处理程序时,有时会发现尽管已经解除了系统对用户同时打开文件数的限制,但仍会出现并发TCP连接数增加到一定数量时,再也无法成功建立新的TCP连接的现象。出现这种现在的原因有多种。

之一种原因可能是因为Linux网络内核对本地端口号范围有限制。此时,进一步分析为什么无法建立TCP连接,会发现问题出在connect()调用返回失败,查看系统错误提示消息是“Can’t assign requestedaddress”。同时,如果在此时用tcpdump工具监视网络,会发现根本没有TCP连接时客户端发SYN包的网络流量。这些情况说明问题在于本地Linux系统内核中有限制。其实,问题的根本原因在于Linux内核的TCP/IP协议实现模块对系统中所有的客户端TCP连接对应的本地端口号的范围进行了限制(例如,内核限制本地端口号的范围为1024~32768之间)。当系统中某一时刻同时存在太多的TCP客户端连接时,由于每个TCP客户端连接都要占用一个唯一的本地端口号(此端口号在系统的本地端口号范围限制中),如果现有的TCP客户端连接已将所有的本地端口号占满,则此时就无法为新的TCP客户端连接分配一个本地端口号了,因此系统会在这种情况下在connect()调用中返回失败,并将错误提示消息设为“Can’t assignrequested address”。有关这些控制逻辑可以查看Linux内核源代码,以linux2.6内核为例,可以查看tcp_ipv4.c文件中如下函数:

static int tcp_v4_hash_connect(struct sock *sk)

请注意上述函数中对变量sysctl_local_port_range的访问控制。变量sysctl_local_port_range的初始化则是在tcp.c文件中的如下函数中设置:

void __init tcp_init(void)

内核编译时默认设置的本地端口号范围可能太小,因此需要修改此本地端口范围限制。

之一步,修改/etc/sysctl.conf文件,在文件中添加如下行:

net.ipv4.ip_local_port_range =

这表明将系统对本地端口范围限制设置为1024~65000之间。请注意,本地端口范围的最小值必须大于或等于1024;而端口范围的更大值则应小于或等于65535。修改完后保存此文件。

第二步,执行sysctl命令:

$ sysctl -p

如果系统没有错误提示,就表明新的本地端口范围设置成功。如果按上述端口范围进行设置,则理论上单独一个进程最多可以同时建立60000多个TCP客户端连接。

第二种无法建立TCP连接的原因可能是因为Linux网络内核的IP_TABLE防火墙对更大跟踪的TCP连接数有限制。此时程序会表现为在 connect()调用中阻塞,如同死机,如果用tcpdump工具监视网络,也会发现根本没有TCP连接时客户端发SYN包的网络流量。由于 IP_TABLE防火墙在内核中会对每个TCP连接的状态进行跟踪,跟踪信息将会放在位于内核内存中的conntrackdatabase中,这个数据库的大小有限,当系统中存在过多的TCP连接时,数据库容量不足,IP_TABLE无法为新的TCP连接建立跟踪信息,于是表现为在connect()调用中阻塞。此时就必须修改内核对更大跟踪的TCP连接数的限制,方法同修改内核对本地端口号范围的限制是类似的:

之一步,修改/etc/sysctl.conf文件,在文件中添加如下行:

net.ipv4.ip_conntrack_max = 10240

这表明将系统对更大跟踪的TCP连接数限制设置为10240。请注意,此限制值要尽量小,以节省对内核内存的占用。

第二步,执行sysctl命令:

$ sysctl -p

如果系统没有错误提示,就表明系统对新的更大跟踪的TCP连接数限制修改成功。如果按上述参数进行设置,则理论上单独一个进程最多可以同时建立10000多个TCP客户端连接。

3、使用支持高并发网络I/O的编程技术

在Linux上编写高并发TCP连接应用程序时,必须使用合适的网络I/O技术和I/O事件分派机制。

可用的I/O技术有同步I/O,非阻塞式同步I/O(也称反应式I/O),以及异步I/O。在高TCP并发的情形下,如果使用同步I/O,这会严重阻塞程序的运转,除非为每个TCP连接的I/O创建一个线程。但是,过多的线程又会因系统对线程的调度造成巨大开销。因此,在高TCP并发的情形下使用同步I /O 是不可取的,这时可以考虑使用非阻塞式同步I/O或异步I/O。非阻塞式同步I/O的技术包括使用select(),poll(),epoll等机制。异步I/O的技术就是使用AIO。

从I/O事件分派机制来看,使用select()是不合适的,因为它所支持的并发连接数有限(通常在1024个以内)。如果考虑性能,poll()也是不合适的,尽管它可以支持的较高的TCP并发数,但是由于其采用“轮询”机制,当并发数较高时,其运行效率相当低,并可能存在I/O事件分派不均,导致部分 TCP连接上的I/O出现“饥饿”现象。而如果使用epoll或AIO,则没有上述问题(早期 Linux内核的AIO技术实现是通过在内核中为每个I/O请求创建一个线程来实现的,这种实现机制在高并发TCP连接的情形下使用其实也有严重的性能问题。但在最新的Linux内核中,AIO的实现已经得到改进)。

Linux下 client server 连不上

read是阻塞的,比如你server在read的时候,帆神server的这个进程就会阻塞在这里了,你的client也是上来就read这样,他也阻塞在这里了,二个人没有人write全read这样就表现成你代码的效果了。大体给改了一下,client上来发个hello,然后server回一下,client再把这个打印。还有,你server的fork部分原来处理有些问题也做了些修改。修改后代码如下:

server:

#include

#include

#include

#include

#include

#include

#include

#include

#define null 0

#define port 7000

#define backlog 10

void process_server(int s)

{

ssize_t size = 0;

char buffer;

// while(1)

{

size = read(s, buffer, 1024);

if(size == 0) return;

}

sprintf(buffer, “%d bytes altogether\n”, size);

printf(“孝拆buffer:%s\n”,buffer);

write(s, buffer, strlen(buffer) + 1);

}

int main(void)

{

struct sockaddr_in sin;

struct sockaddr_in cin;

int SS;

int SC;

int addrlen = sizeof(struct sockaddr);

pid_t pid;

int err;

SS = socket(AF_INET, SOCK_STREAM, 0);

if(SS 0)

{ //父进程继续监听

close(SC);

} else if (pid == 0) {//子进程处理这样写容易产生僵死态慎亏进程

process_server(SC);

close(SC);

} else {//error

close(SC);

}

}

return 0;

}

client:

#include

#include

#include

#include

#include

#include

#include

#include

#define null 0

#define port 7000

#define backlog 10

void process_client(int s)

{

ssize_t size = 0;

char buffer;

// while(1)

{

// size = read(0, buffer, 1024);

// if(size > 0)

{

// write(s, buffer, size);

write(s,”hello”, sizeof(“hello”));

printf(“write over\n”);

size = read(s, buffer, 1024);

printf(“buffer:%s\n”,buffer);

// write(1, buffer, size);

}

}

}

int main(int argc, char *argv)

{

struct sockaddr_in cin;

int SC;

int err;

close(SC);

SC = socket(AF_INET, SOCK_STREAM, 0);

if(SC

----------------

client:

strace -p 4574

Process 4574 attached – interrupt to quit

read(3, ^C 谨毁

主机的防火墙是必须关的。

主机上使用软件连接登陆VMWare上的Linux,有两种方式可以慧举连接:

(1)桥接方式: 使主机与Linux的IP在同一个网段中,就可以了,这样主机必须要插上网线。

关于tcp server linux的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

成都创新互联科技有限公司,是一家专注于互联网、IDC服务、应用软件开发、网站建设推广的公司,为客户提供互联网基础服务!
创新互联(www.cdcxhl.com)提供简单好用,价格厚道的香港/美国云服务器和独立服务器。创新互联成都老牌IDC服务商,专注四川成都IDC机房服务器托管/机柜租用。为您精选优质idc数据中心机房租用、服务器托管、机柜租赁、大带宽租用,可选线路电信、移动、联通等。

本文标题:LinuxTCP服务器:构建高效稳定的网络通信(tcpserverlinux)
文章位置:http://www.shufengxianlan.com/qtweb/news7/361357.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联