Linux 下socket编程 connect()函数返回-1(error:Connection refused)

一、背景
系统:CentOS7 64位 物理机
IP:192.168.2.199/24
使用端口:9999
二、问题描述
在tty1上运行服务器程序,在tty2上运行客户端程序
若连接成功,则服务器程序会向客户端程序发送“Hello World!”字符串。
服务端正常监听,但是客户端在连接时却连接不上,connect()函数返回-1。

服务端部分代码

int main(int argc, char *argv[])
{
	int serv_sock, clnt_sock;

	struct sockaddr_in serv_addr, clnt_addr;
	socklen_t clnt_addr_size;

	char message[] = "Hello World!";

	if(argc != 2)
	{
		printf("Usage: %s <port>\n", argv[0]);
		exit(1);
	}

	serv_sock = socket(AF_INET, SOCK_STREAM, 0);
	if(serv_sock == -1)
		handling_error("socket() error");

	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htonl(atoi(argv[1]));

	if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
		handling_error("bind() error");

	if(listen(serv_sock, 5) == -1)
		handling_error("listen() err
<think>我们正在解决两个独立的错误:1.`__init__()gotanunexpectedkeywordargument'timeout'`:这是Python代码中调用构造函数时传递了不被接受的参数`timeout`。2.`ERROR61Connectionrefused`:这是网络连接错误,表示尝试连接的目标服务未运行或防火墙阻止。首先,我们分别处理这两个错误,然后考虑它们可能的关联。##错误1:`__init__()gotanunexpectedkeywordargument'timeout'`此错误发生在创建SMB连接对象时。根据之前的分析,可能的原因和解决方案如下:###原因-使用的SMB库(如`pysmb`或`smbprotocol`)的版本不兼容,新版本中可能移除了构造函数中的`timeout`参数。-将`timeout`参数传递给了错误的函数(应该传递给`connect()`方法而不是构造函数)。###解决方案1.**检查库版本和文档**:-确认当前安装的SMB库版本,例如对于`pysmb`:```bashpipshowpysmb```-查阅该版本的官方文档,确定正确的参数传递方式。2.**调整参数传递位置**:-对于`pysmb`库,`timeout`参数应该传递给`connect()`方法,而不是`SMBConnection`的构造函数-错误示例:```pythonfromsmb.SMBConnectionimportSMBConnectionconn=SMBConnection(username,password,...,timeout=30)#错误:在构造函数中传递timeout```-正确示例:```pythonconn=SMBConnection(username,password,...)#不传递timeoutconn.connect(server_ip,port,timeout=30)#在connect方法中传递```3.**升级或降级库版本**:-如果使用旧版本代码,但库已升级,可以考虑降级到支持该参数的版本(例如`pysmb==1.2.6`):```bashpipinstallpysmb==1.2.6```-或者升级到最新版本并按照新版本API修改代码。4.**使用新参数名**:-在较新的库版本中,可能使用了不同的参数名,例如`connection_timeout`或`session_timeout`。需要查阅文档确认。##错误2:`ERROR61Connectionrefused`此错误发生在尝试建立SMB连接时,表示客户端无法连接到目标服务器的SMB服务。###原因-目标服务器未运行SMB服务(如Samba或Windows文件共享服务)。-目标服务器上的SMB服务未在指定端口(通常是445)监听。-防火墙(服务器端或客户端)阻止了连接。-服务器IP地址或端口号配置错误。-在本地环境中,可能是服务未启动或配置问题(如引用[1]中提到的Celery连接AMQP失败,类似网络连接问题)。###解决方案1.**检查SMB服务状态**:-在目标服务器上,确认SMB服务正在运行。-Windows:检查“Server”服务以及“TCP/IPNetBIOSHelper”服务是否运行。-Linux(Samba):运行`sudosystemctlstatussmbd`查看服务状态。2.**检查端口监听情况**:-在目标服务器上,使用以下命令检查端口(默认445)是否在监听:```bash#Linuxsudonetstat-tuln|grep445#Windowsnetstat-an|findstr445```3.**检查防火墙设置**:-确保目标服务器防火墙允许入站连接端口445(TCP)。-Linux(ufw):`sudoufwallow445/tcp`-Windows:在“高级安全Windows防火墙”中添加入站规则。4.**验证网络连通性**:-从客户端尝试连接服务器端口445(使用telnet或nc):```bashtelnetserver_ip445```如果无法连接,说明网络问题或服务未监听。5.**检查服务器配置**:-Samba配置(`/etc/samba/smb.conf`)是否正确,特别是`interfaces`和`hostsallow`设置。6.**考虑IPv4/IPv6问题**:-如引用[2]中提到,某些情况下服务可能绑定到IPv6而客户端使用IPv4,或相反。-在客户端连接时,明确使用IPv4地址(如`127.0.0.1`)或检查服务器是否同时监听IPv4和IPv6。##两个错误同时出现的处理步骤假设代码中同时出现了这两个错误,我们需要按顺序解决:1.先解决`timeout`参数错误,确保代码能正确创建连接对象。2.再解决连接拒绝错误,确保网络服务可用。##示例代码修正假设使用`pysmb`库,修正后的代码结构:```pythonfromsmb.SMBConnectionimportSMBConnection#创建连接对象(不在构造函数中传递timeout)conn=SMBConnection(username='your_username',password='your_password',my_name='client_machine_name',remote_name='server_name')#在连接时指定timeouttry:#尝试连接(服务器IP、端口、超时)conn.connect('192.168.1.100',445,timeout=30)exceptExceptionase:print(f"连接失败:{str(e)}")#处理连接错误else:#连接成功,执行操作files=conn.listPath('share_name','/')#...conn.close()```##调试提示-使用Wireshark抓包分析SMB连接建立过程。-检查服务器日志(Samba日志位于`/var/log/samba/`,Windows查看事件查看器)。##相关问题§§相关问题§§1.Samba服务常见配置错误有哪些?2.如何在Python中捕获并处理SMB连接超时异常?3.如何为SMB文件传输设置读写超时参数?4.在Linux系统调试SMB连接失败的通用方法有哪些?5.如何在Windows防火墙中开放SMB端口?</think> 针对SMB连接的两类错误(`__init__() timeout参数异常` 和 `ERROR 61 Connection refused`),以下是分层解决方案: --- ### 一、`__init__() timeout`参数错误解决方案 **问题本质**:SMB库API版本不兼容,构造函数参数签名变更 #### 🔧 方法1:参数位置修正(以pysmb为例) ```python from smb.SMBConnection import SMBConnection # ❌ 错误写法(timeout在构造函数) # conn = SMBConnection(username, password, timeout=30) # ✅ 正确写法(timeout在connect方法) conn = SMBConnection(username, password) # 不包含timeout conn.connect(server_ip, 445, timeout=30) # 超时参数移至连接方法[^1] ``` #### 🔧 方法2:API版本适配 ```bash # 安装兼容版本(根据库名选择) pip install pysmb==1.2.6 # 旧版支持构造函数timeout # 或 pip install smbprotocol==1.6.0 # 新版用 session_timeout 参数 ``` 新版smbprotocol的正确参数: ```python from smbprotocol.connection import Connection conn = Connection(..., session_timeout=30) # ✅ 新参数名[^2] ``` --- ### 二、`ERROR 61 Connection refused`解决方案 **问题本质**:服务未响应/网络配置错误 ![](https://via.placeholder.com/600x200?text=SMB连接拓扑示意图) #### 🔧 网络层检查(优先级排序) 1. **服务状态验证** ```bash # Linux (Samba服务) sudo systemctl status smbd nmbd # Windows Get-Service -Name LanmanServer, LanmanWorkstation ``` 2. **端口监听检测** ```bash # 目标服务器执行 netstat -an | grep 445 # 确认监听状态 telnet <server_ip> 445 # 客户端测试连接[^1] ``` 3. **防火墙策略解封** ```bash # Linux ufw sudo ufw allow 445/tcp # Windows防火墙 New-NetFirewallRule -DisplayName "SMB" -Direction Inbound -Protocol TCP -LocalPort 445 -Action Allow ``` #### 🔧 配置层修复 ```ini # /etc/samba/smb.conf 关键配置[^2] [global] interfaces = 127.0.0.1 eth0 192.168.1.0/24 # 绑定IPv4地址 bind interfaces only = yes smb ports = 445 ``` #### 🔧 连接代码增强 ```python import socket # 预检网络连通性 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(3.0) try: sock.connect((server_ip, 445)) # 基础TCP连接测试 except ConnectionRefusedError: print("⚠️ 服务未运行或防火墙阻止") # 返回61错误的根因 ``` --- ### 三、联合调试流程 1. **环境验证** ```mermaid graph LR A[代码timeout参数位置] --> B{参数是否在connect方法} B -->|否| C[修正参数位置] B -->|是| D[检查SMB服务状态] D --> E[端口监听测试] E --> F[防火墙策略验证] ``` 2. **日志分析命令** ```bash # Samba服务日志 tail -f /var/log/samba/log.smbd # Windows事件日志 Get-WinEvent -LogName Microsoft-Windows-SMBClient/Connectivity ``` --- ### 关键修复总结表 | 错误类型 | 根因 | 解决方案 | |---------------------------|---------------------------|---------------------------------------| | `__init__() timeout` | API参数签名变更 | 移动参数到connect方法或改用session_timeout | | `ERROR 61` | TCP层连接失败 | 检查服务状态/防火墙/端口绑定 | | 超时+拒绝同时出现 | 复合型网络配置错误 | 按网络层→配置层→代码层顺序逐级排查 | > ⚠️ **注意**:在IPv6环境下出现连接拒绝时(如引用[2]类似场景),需强制使用IPv4协议栈: > ```python > conn.connect(server_ip, 445, timeout=30, forceIPv4=True) # pysmb参数 > ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值