Linux 下socket编程 connect()函数返回

您所在的位置:网站首页 错误码1101是什么原因 Linux 下socket编程 connect()函数返回

Linux 下socket编程 connect()函数返回

2024-07-13 13:17| 来源: 网络整理| 查看: 265

一、背景 系统: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 \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() error"); clnt_addr_size = sizeof(clnt_addr); clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_size); if(clnt_sock == -1) handling_error("accept() error"); write(clnt_sock, message, sizeof(message)); close(clnt_sock); close(serv_sock); return 0; }

客户端部分代码

int main(int argc, char *argv[]) { int sock; struct sockaddr_in serv_addr; char message[30]; int str_len; if(argc != 3) { printf("Usage: %s \n", argv[0]); exit(1); } sock = socket(AF_INET, SOCK_STREAM, 0); if(sock == -1) error_handling("socket() error"); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr = inet_addr(argv[1]); serv_addr.sin_port = htons(atoi(argv[2])); if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) error_handling("connect() error!"); str_len = read(sock, message, sizeof(message) - 1); if(str_len == -1) error_handling("read() error!"); printf("Message from server: %s \n", message); close(sock); return 0; } 三、问题解决

在上面两部分代码中使用了error_handling自定义函数,为了找出错误原因,调用了perror(const char *message)函数,该函数会打印message字符串,并在其后打印errno变量,Linux中系统调用的错误都存储于 errno中,errno由操作系统维护,存储就近发生的错误,即下一次的错误码会覆盖掉上一次的错误。

error_handling(char *message)函数

void error_handling(char *message) { perror(message); exit(1); }

运行后,客户端报错:connect() error!:Connection refused,即链接请求被拒绝,在看了一遍程序没有发现明显错误后,我想看一下8888端口是否在使用。

lsof -i:8888

结果出来为空,8888端口并没有被使用。然后我再查看服务器进程在使用哪个端口。

netstat -tnlp

然后发现服务端程序正常监听,但是端口不是8888,而是39388,这意味着是操作系统给随机分配了一个端口,而没有使用我们指定的端口。 回到服务端程序,仔细查看初始化套接字的那段代码,找出了错误。 端口为16位,在转换主机字节序和网络字节序的时候使用了htonl(),htonl()函数是进行32位的转换,CentOS7系统采用的字节序为小端字节序。 假如采用htonl() 假如采用htonl()函数,则操作系统会选择[0x20, 0x21)段的值作为端口号,因此,htonl(8888)的实际结果为0而非8888的网络字节序。由于端口的实际值为0,这会导致当服务端调用函数listen时,内核会为服务端选择一个临时端口,这个临时端口通常与我们所指定的端口并不相同。 因此将htonl()函数换为htons()函数就能解决这个问题了。

四、总结

引起Connection refused的可能原因:服务端在客户端所请求的端口上没有服务在等待连接。

也许是服务端根本没有启动;也许是服务端启动成功了,但客户端所请求的端口与服务端正在监听的端口不一致(客户端所请求的端口并不一定与我们所指定的一致,服务端正在监听的端口也并不一定与我们所指定的一致,这正是本文所讨论的内容)。当然,不排除还存在其他情况会导致此错误,只是笔者还未遇到或听说而已。

五、参考文章:

Connection refused问题的解决:https://blog.csdn.net/wohenfanjian/article/details/51118895 errno:https://www.cnblogs.com/fjutacm/p/5969c7593fdb6516c11a55b0e6813938.html http://www.cnblogs.com/Jimmy1988/p/7485133.html lsof安装:https://blog.csdn.net/qq_38158631/article/details/78684723 netstat命令安装:https://blog.csdn.net/zpwangshisuifeng/article/details/78526873?locationNum=7&fps=1



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3