linux
Linux中本机和本机Socket通信会走网卡吗?
一、Linux中本机和本机Socket通信会走网卡吗?
旗帜鲜明说观点,本机之间的Socket通信,有可能走网卡,剩下的全部不走网卡。
这是一道路由(IP Routing)题,所以这道题只和IP Routing有关,即TCP/IP协议栈的IP路由有关。
不走网卡的场景
场景1:服务器IP = 127.0.0.1
服务器IP =127.0.0.1,即IP包的目IP=127.0.0.1,那IP包的源IP地址是什么?
IP模块基于目的IP =127.0.0.1,查询路由表发现最佳路由的出口为虚拟接口(127.0.0.1),于是就用它(127.0.0.1)作为源IP,它距离目的地最近。这是操作系统默认行为,如果用户没有明确指定源IP地址,操作系统选择路由出接口(Exiting Interface)的IP地址。
既然IP包已经完成了封装,IP Routing按照路由查询结果进行发送,并进入Sending Queue,IP Routing有一个判断逻辑,如果IP包的目的IP == 本地接口IP,需要将Sending Queue的该IP包移入Receiving Queue,相当于发送线与接收线短接(loopback)。
然后该IP包按照IP路由提交给虚拟接口(127.0.0.1),IP包没有经过网卡。
场景2:服务器IP = 10.1.1.1,IP绑定一个硬件网卡
同上,由于用户没有指定源IP,系统默认使用10.1.1.1作为源IP。该IP包被IP Routing做了收发短接,IP包在IP Routing模块里即发生了收发,IP包不经过网卡。
场景3:服务器IP = 10.1.1.1(一块网卡),客户端10.1.1.2 (同机另一块网卡),开启多接口路由功能
服务器IP =10.1.1.1,即IP包的目IP=10.1.1.1,源IP = 10.1.1.2 (由用户明确指定)。操作系统开启了多个网络接口IP Routing功能,如下图所示:
此时主机是一台路由器,该IP包被IP Routing做了收发短接,IP包在IP Routing模块里即发生了收发,IP包不经过网卡。
走网卡的场景
场景4:服务器IP = 10.1.1.1(一块网卡),客户端10.1.1.2 (同机另一块网卡),关闭多接口路由功能。
这个场景非常容易让人迷惑,之所以容易迷惑,是因为尽管服务器有两块网卡,但是这两块网卡老死不相往来。如果没有其它网络设备的帮助,是无法通信的,因为两块网卡之间的路由功能已经关闭,如下图所示:
目的IP =10.1.1.1,按照正常查询路由表的决策,最优路由(10.1.1.1/32,匹配长度为32bit)的出接口为10.1.1.1接口,那么应该使用10.1.1.1接口的IP= 10.1.1.1作为源IP地址,但是这和客户端指定的IP = 10.1.1.2并不相同,很显然无法满足客户端的需求。
于是,在次优路由里看看是否有满足用户需求的路由条目,值得欣慰的是,确实有这么一条次优路由(10.1.1.0/24,匹配长度为24bit),这条路由对应的出接口为10.1.1.2,系统会使用该接口的IP =10.1.1.2 作为源IP地址,恰好满足客户的需求。
然后这个IP包完成封装,进入Sending Queue,接下来会发生什么?
有同学说,由于IP包的目的IP地址 = 10.1.1.1, 恰好满足上文的判断逻辑,收发短接,同样不会经过网卡,对吗?
不对!
上文说了,这两块网卡是两个平行世界的接口,所以上文的判断逻辑不再适用。在出接口10.1.1.2的平行世界里,本地只有自己一个接口,接口10.1.1.1并不存在。
所以,接下来的一切主机之间的通信,就仿佛是两个主机之间的通信。需要发ARP广播请求对方的MAC地址,ARP通过网卡到达交换机,然后交换机广播ARP,ARP请求到达10.1.1.1。
服务器10.1.1.1发送ARP回复,经过网卡到达交换机,然后再到达主机10.1.1.2。最后两个主机就可以通信了,整个通信过程都会经过网卡。
上文的Routing的开关,在Windows操作系统使用“Services.msc” 设置”Routing and Remote Access”完成,Linux系统应该也有对应的开关配置。
二、linux下socket编程中close()函数?
只要不用close或fclose,不管把这个socket_fd值存到哪里,都可以使用。比如:
int socket_fd = socket(...);
int socket_x = socket_fd;
那么send(socket_x)和send(socket_fd)结果完全一致
三、linux虚拟机进行socket通信要如何设置?
请终端下输入
sudo netstat -a
如果看到了,如果能看到很多unix的链接流。则证明linux系统本身已经启用了很多socket通信。已经是设置好的。
至于如何进行socket通信编程。请寻找相关资料自学。
如果你只是想建立到远端服务器的一个ip隧道。架设加密代理的隧道,那么请告知你使用的linux版本,以及使用的软件。
四、socket通信原理?
通信原理是服务器端先初始化Socket;然后与端口绑定,对端口进行监听,调用accept阻塞,等待客户端连接。
客户端连接成功后,客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接。
五、socket通信readtimeout?
可能:
1,socket读不到流的结尾,会一直不停等待客户端输入 超时read time out。
服务端逻辑可能存在问题。2,客户端组织报文是否存在问题,比如,存在报文长度的标志等,要跟踪一下,看看是否存在错误。
3,网络是否存在问题,比如存在防火墙单向阻止了。得根据实际情况来看啊。
六、linux下每个socket会占用多少内存?
net.ipv4.tcp_wmem = 4096 16384 4194304net.ipv4.tcp_rmem = 4096 87380 4194304就是说,每个tcp连接的socket,至少需要8k字节,那么对于8G内存的机器,如果不考虑swap等其他因素,最多支持并发100万个tcpsocket
七、怎么进行socket通信?
设计思路
本例包括一个服务器端程序和一个客户端程序。客户端程序可以放到多个计算机上运行,同时与服务器端进行连接通信。
本例的重点,一是演示客户端与服务器端如何通信;二是当有多个客户端同时连接到服务器端时,服务器端如何识别每个客户端,并对请求给出相应的回复。为了保证一个客户端断开连接时不影响其它客户端与服务器端的通信,同时保证服务器端能够正确回复客户端的请求,在本例中声明了一个记录类型:
type
client_record=record
CHandle:integer;//客户端套接字句柄
CSocket:TCustomWinSocket;//客户端套接字
CName:string;//客户端计算机名称
CAddress:string;//客户端计算机IP地址
CUsed:boolean;//客户端联机标志
end;
利用这个记录类型数据保存客户端的信息,同时保存当前客户端的连接状态。其中,CHandle保存客户端套接字句柄,以便准确定位每个与服务器端保持连接的客户端;Csocket保存客户端套接字,通过它可以对客户端进行回复。Cused记录当前客户端是否与服务器端保持连接。
下面对组件ServerSocket和ClientSocket的属性设置简单说明。
ServerSocket的属性:
·Port,是通信的端口,必须设置。在本例中设置为1025;
·ServerTypt,服务器端读写信息类型,设置为stNonBlocking表示异步读写信息,本例中采用这种方式。
·ThreadCacheSize,客户端的最大连接数,就是服务器端最多允许多少客户端同时连接。本例采用默认值10。
其它属性采用默认设置即可。
ClientSocket的属性:
·Port,是通信的端口,必须与服务器端的设置相同。在本例中设置为1025;
·ClientType,客户端读写信息类型,应该与服务器端的设置相同,为stNonBlocking表示异步读写信息。
·Host,客户端要连接的服务器的IP地址。必须设置,当然也可以在代码中动态设置。
其它属性采用默认设置即可。
程序源代码:
·服务器端源码(uServerMain.pas):
unituServerMain;
interface
uses
Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,
ScktComp,ToolWin,ComCtrls,ExtCtrls,StdCtrls,Buttons;
const
CMax=10;//客户端最大连接数
type
client_record=record
CHandle:integer;//客户端套接字句柄
CSocket:TCustomWinSocket;//客户端套接字
CName:string;//客户端计算机名称
CAddress:string;//客户端计算机IP地址
CUsed:boolean;//客户端联机标志
end;
type
TfrmServerMain=class(TForm)
ServerSocket:TServerSocket;
ControlBar1:TControlBar;
ToolBar1:TToolBar;
tbConnect:TToolButton;
tbClose:TToolButton;
tbDisconnected:TToolButton;
Edit1:TEdit;
Memo1:TMemo;
StatusBar:TStatusBar;
proceduretbConnectClick(Sender:TObject);
proceduretbDisconnectedClick(Sender:TObject);
procedureServerSocketClientRead(Sender:TObject;Socket:TCustomWinSocket);
procedureServerSocketListen(Sender:TObject;Socket:TCustomWinSocket);
procedureServerSocketClientConnect(Sender:TObject;Socket:TCustomWinSocket);
procedureServerSocketClientDisconnect(Sender:TObject;Socket:TCustomWinSocket);
proceduretbCloseClick(Sender:TObject);
procedureFormCreate(Sender:TObject);
procedureFormClose(Sender:TObject;varAction:TCloseAction);
procedureServerSocketGetSocket(Sender:TObject;Socket:Integer;
varClientSocket:TServerClientWinSocket);
procedureServerSocketClientError(Sender:TObject;
Socket:TCustomWinSocket;ErrorEvent:TErrorEvent;
varErrorCode:Integer);
private
{
Privatedeclarations
}
public
{
Publicdeclarations
}
session:array[0..CMax]ofclient_record;//客户端连接数组
Sessions:integer;//客户端连接数
end;
var
frmServerMain:TfrmServerMain;
implementation
{$R*.DFM}
//打开套接字连接,并使套接字进入监听状态
procedureTfrmServerMain.tbConnectClick(Sender:TObject);
begin
ServerSocket.Open;
end;
//关闭套接字连接,不再监听客户端的请求
procedureTfrmServerMain.tbDisconnectedClick(Sender:TObject);
begin
ServerSocket.Close;
StatusBar.Panels[0].Text:='服务器套接字连接已经关闭,无法接受客户端的连接请求.';
end;
//从客户端读取信息
procedureTfrmServerMain.ServerSocketClientRead(Sender:TObject;Socket:TCustomWinSocket);
var
i:integer;
begin
//将从客户端读取的信息添加到Memo1中
Memo1.Lines.Add(Socket.ReceiveText);
fori:=0tosessionsdo
begin
//取得匹配的客户端
ifsession[i].CHandle=Socket.SocketHandlethen
begin
session[i].CSocket.SendText('回复客户端'+session[i].CAddress+'==>'+Edit1.Text);
end;
end;
end;
//服务器端套接字进入监听状态,以便监听客户端的连接
procedureTfrmServerMain.ServerSocketListen(Sender:TObject;Socket:TCustomWinSocket);
begin
StatusBar.Panels[0].Text:='等待客户端连接...';
end;
//当客户端连接到服务器端以后
procedureTfrmServerMain.ServerSocketClientConnect(Sender:TObject;
Socket:TCustomWinSocket);
var
i,j:integer;
begin
j:=-1;
fori:=0tosessionsdo
begin
//在原有的客户端连接数组中有中断的客户端连接
ifnotsession[i].CUsedthen
begin
session[i].CHandle:=Socket.SocketHandle;//客户端套接字句柄
session[i].CSocket:=Socket;//客户端套接字
session[i].CName:=Socket.RemoteHost;//客户端计算机名称
session[i].CAddress:=Socket.RemoteAddress;//客户端计算机IP
session[i].CUsed:=True;//连接数组当前位置已经占用
Break;
end;
j:=i;
end;
ifj=sessionsthen
begin
inc(sessions);
session[j].CHandle:=Socket.SocketHandle;
session[j].CSocket:=Socket;
session[j].CName:=Socket.RemoteHost;
session[j].CAddress:=Socket.RemoteAddress;
session[j].CUsed:=True;
end;
StatusBar.Panels[0].Text:='客户端'+Socket.RemoteHost+'已经连接';
end;
//当客户端断开连接时
procedureTfrmServerMain.ServerSocketClientDisconnect(Sender:TObject;
Socket:TCustomWinSocket);
var
i:integer;
begin
fori:=0tosessionsdo
begin
ifsession[i].CHandle=Socket.SocketHandlethen
begin
session[i].CHandle:=0;
session[i].CUsed:=False;
Break;
end;
end;
StatusBar.Panels[0].Text:='客户端'+Socket.RemoteHost+'已经断开';
end;
//关闭窗口
procedureTfrmServerMain.tbCloseClick(Sender:TObject);
begin
Close;
end;
procedureTfrmServerMain.FormCreate(Sender:TObject);
begin
sessions:=0;
end;
procedureTfrmServerMain.FormClose(Sender:TObject;varAction:TCloseAction);
begin
ServerSocket.Close;
end;
//当客户端正在与服务器端连接时
procedureTfrmServerMain.ServerSocketGetSocket(Sender:TObject;
Socket:Integer;varClientSocket:TServerClientWinSocket);
begin
StatusBar.Panels[0].Text:='客户端正在连接...';
end;
//客户端发生错误
procedureTfrmServerMain.ServerSocketClientError(Sender:TObject;
Socket:TCustomWinSocket;ErrorEvent:TErrorEvent;
varErrorCode:Integer);
begin
StatusBar.Panels[0].Text:='客户端'+Socket.RemoteHost+'发生错误!';
ErrorCode:=0;
end;
end.
八、Linux下利用socket编程实现文件传输?
要下班了,时间急,不写代码了先给你一个思路
1 实现最简单的udp socket 模型,实现发送一个字符串。
2 实现一个简单的打开文件,读取文件的例子,如用fgets(),类似的函数有很多,然后再把读取的文件内容忘另一个文件里写(相关函数fopen(),write(),read())。
3 把上面两个函数结合到一起,在客户端实现打开要传送的文件,按一定的大小读取,读取后调用sendto()发送到服务器端。在服务器端创建一个文件,然后调用recvfrom()接受客户端发送过来的数据,向来是创建的那个文件中写。 下面是改好的udp发送文件的例子。服务器端程序的编译gcc -o file_server file_server客户端程序的编译gcc -o file_client file_client.c服务器程序和客户端程应当分别运行在2台计算机上.服务器端程序的运行,在一个计算机的终端执行./file_server客户端程序的运行,在另一个计算机的终端中执行./file_client 运行服务器程序的计算机的IP地址根据提示输入要传输的服务器上的文件,该文件在服务器的运行目录上在实际编程和测试中,可以用2个终端代替2个计算机,这样就可以在一台计算机上测试网络程序,服务器端程序的运行,在一个终端执行./file_server客户端程序的运行,在另一个终端中执行./file_client 127.0.0.1说明: 任何计算机都可以通过127.0.0.1访问自己. 也可以用计算机的实际IP地址代替127.0.0.1//////////////////////////////////////////////////////////////////////////////////////// file_server.c 文件传输顺序服务器示例////////////////////////////////////////////////////////////////////////////////////////本文件是服务器的代码#include
九、linux socket文件的作用?
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
十、app是api通信还是socket通信?
后端,也只提供了一系列的功能给app使用,这系列的功能以api的形式提供。
api的定义:API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
热点信息
-
在Python中,要查看函数的用法,可以使用以下方法: 1. 使用内置函数help():在Python交互式环境中,可以直接输入help(函数名)来获取函数的帮助文档。例如,...
-
一、java 连接数据库 在当今信息时代,Java 是一种广泛应用的编程语言,尤其在与数据库进行交互的过程中发挥着重要作用。无论是在企业级应用开发还是...
-
一、idea连接mysql数据库 php connect_error) { die("连接失败: " . $conn->connect_error);}echo "成功连接到MySQL数据库!";// 关闭连接$conn->close();?> 二、idea连接mysql数据库连...
-
要在Python中安装modbus-tk库,您可以按照以下步骤进行操作: 1. 确保您已经安装了Python解释器。您可以从Python官方网站(https://www.python.org)下载和安装最新版本...