linux 服务器与客户端异常断开连接问题

服务器与客户端连接,客户端异常断掉之后服务器端口仍然被占用, 到最后是不是服务器端达到最大连接数就没法连接了?领导让我测试这种情况,我用自己的电脑当TCP Client,虚拟机当服务器,连接之后能正常通信,每次拔掉网线断开,5次之后就不能连接了(我的服务器设置最大连接数就是5)。具体如下:1:用模拟软件Commix模拟TCP Client,连接服务器。

2:用服务器端监听端口1234。重复打开关闭TCP Client的端口,服务器显示如下图所示:

1——5次可以正常连接,5次完成之后出现如下问题:
 
请问怎么解决这一问题,让服务器端自动清除已断掉的连接。
socket程序如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define MYPORT 1234    // the port users will be connecting to

#define BACKLOG 5     // how many pending connections queue will hold

#define BUF_SIZE 200

int fd_A[BACKLOG];    // accepted connection fd
int conn_amount;    // current connection amount

void showclient()
{
    int i;
    printf("client amount: %d\n", conn_amount);
    for (i = 0; i < BACKLOG; i++) {
        printf("[%d]:%d  ", i, fd_A);
    }
    printf(
"\n\n");
}

int main(void)
{
    int sock_fd, new_fd;  // listen on sock_fd, new connection on new_fd
    struct sockaddr_in server_addr;    // server address information
    struct sockaddr_in client_addr; // connector‘s address information
    socklen_t sin_size;
    int yes = 1;
    char buf[BUF_SIZE];
    int ret;
    int i;

if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }
    
    server_addr.sin_family = AF_INET;         // host byte order
    server_addr.sin_port = htons(MYPORT);     // short, network byte order
    server_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
    memset(server_addr.sin_zero, ‘\0‘, sizeof(server_addr.sin_zero));

if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind");
        exit(1);
    }

if (listen(sock_fd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }

printf("listen port %d\n", MYPORT);

fd_set fdsr;
    int maxsock;
    struct timeval tv;

conn_amount = 0;
    sin_size = sizeof(client_addr);
    maxsock = sock_fd;
    while (1) {
        // initialize file descriptor set
        FD_ZERO(&fdsr);
        FD_SET(sock_fd, &fdsr);

// timeout setting
        tv.tv_sec = 30;
        tv.tv_usec = 0;

// add active connection to fd set
        for (i = 0; i < BACKLOG; i++) {
            if (fd_A != 0) {
                FD_SET(fd_A&fdsr);
            }
        }

ret = select(maxsock + 1, &fdsr, NULL, NULL, &tv);
        if (ret < 0) {
            perror("select");
            break;
        } else if (ret == 0) {
            printf("timeout\n");
            continue;
        }

// check every fd in the set
        for (i = 0; i < conn_amount; i++) {
            if (FD_ISSET(fd_A&fdsr)) {
                ret = recv(fd_A, buf, sizeof(buf), 0);
                if (ret <= 0) {        // client close
                    printf("client[%d] close\n", i);
                    close(fd_A);
                    FD_CLR(fd_A
&fdsr);
                    fd_A = 0;
                } else {        // receive data
                    if (ret < BUF_SIZE)
                        memset(&buf[ret], ‘\0‘, 1);
                    printf("client[%d] send:%s\n", i, buf);
                }
            }
        }

// check whether a new connection comes
        if (FD_ISSET(sock_fd, &fdsr)) {
            new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
            if (new_fd <= 0) {
                perror("accept");
                continue;
            }

// add to fd queue
            if (conn_amount < BACKLOG) {
                fd_A[conn_amount++] = new_fd;
                printf("new connection client[%d] %s:%d\n", conn_amount,
                        inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
                if (new_fd > maxsock)
                    maxsock = new_fd;
            }
            else {
                printf("max connections arrive, exit\n");
                send(new_fd, "bye", 4, 0);
                close(new_fd);
                break;
            }
        }
        showclient();
    }

// close other connections
    for (i = 0; i < BACKLOG; i++) {
        if (fd_A != 0) {
            close(fd_A);
        }
    }

exit(0);
}

时间: 2024-11-07 06:14:54

linux 服务器与客户端异常断开连接问题的相关文章

Tcp服务端判断客户端是否断开连接

今天搞tcp链接弄了一天,前面创建socket,绑定,监听等主要分清自己的参数,udp还是tcp的.好不容易调通了,然后就是一个需求,当客户端主动断开连接时,服务端也要断开连接,这样一下次客户端请求链接的时候才能成功链接. 然后就开始找各种方法.其中简单的是看recv()返回为0,表明断开了链接,但是recv函数始终返回SOCKET_ERROR,找不到原因............ 参考的方法: 下面来罗列一下判断远端已经断开的方法: 法一: 当recv()返回值小于等于0时,socket连接断开

Netty服务器自动识别客户端已断开

最近开发了使用的Netty的长连接服务器,客户端支持使用socket和websocket的js连接,也可以使用flash连接.但是遇到一个很麻烦的问题,当客户端的网络断开或因为异常断开的时候,服务器并不能立即自动知道客户端已断开.幸好遇到一个同事,比较熟悉网络,因此帮忙解决了这个问题,特此写在这,希望能帮助使用netty的朋友们. 之前尝试解决问题的时候,看了源码,发现了一个方法: public class TextWebSocketFrameHandler extends SimpleChan

解决Linux服务器更换IP后,ssh连接被拒绝问题

解决更换Linux服务器IP后,ssh登录报“ssh: connect to host xxx port 22: Connection refused”错误 由于之前服务器的sshd服务一直正常,但更换IP后通过putty进行登录,报“连接被拒绝”异常 一.重启sshd服务,查看登录是否正常,如果还有异常进行下面步骤 netstat sshd 二.将.ssh/known_hosts文件里面的IP地址修改正确 1.vi ~/.ssh/known_hosts 2.将老IP地址全部替换在新的IP地址

unity客户端自动断开连接

问题描述: 当unity失去焦点一段时间后,与photon服务器端断开连接 问题根源: 默认unity失去焦点后会暂停运行,导致连接超时,服务器端超时断开连接 解决方案: 连接服务器后,填加一句代码让unity在失去焦点的情况下继续执行游戏 Application.runInBackground = true; 原文地址:https://www.cnblogs.com/fzxiaoyi/p/8449684.html

(笔记)Linux服务器中判断客户端socket断开连接的方法

下面来罗列一下判断远端已经断开的方法:(转自http://blog.csdn.net/god2469/article/details/8801356) 法一: 当recv()返回值小于等于0时,socket连接断开.但是还需要判断 errno是否等于 EINTR,如果errno == EINTR 则说明recv函数是由于程序接收到信号后返回的,socket连接还是正常的,不应close掉socket连接. 法二: struct tcp_info info;   int len=sizeof(in

服务器中判断客户端socket断开连接的方法

1, 如果服务端的Socket比客户端的Socket先关闭,会导致客户端出现TIME_WAIT状态,占用系统资源. 所以,必须等客户端先关闭Socket后,服务器端再关闭Socket才能避免TIME_WAIT状态的出现. 2, 在linux下写socket的程序的时候,如果尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号. client端通过 pipe 发送信息到server端后,就关闭client端, 这时server端,返回信息给 client

在Linux服务器、客户端中构建密钥对验证进行远程连接

构建密钥对验证SSH体系的基本过程包括四步: SSH客户端:192.168.1.1SSH服务器:192.168.1.2 1.在客户端创建密钥对: [[email protected] /]# ssh-keygen -t ecdsa # " -t " 用来指定加密算法,这里使用ecdsa,还有一个是dsa. Generating public/private ecdsa key pair. Enter file in which to save the key (/root/.ssh/i

在Linux服务器、客户端之间构建密钥对验证进行远程连接

客户端:192.168.1.10 zhangsan用户服务端:192.168.1.20 lisi用户在客户端中创建密钥对: [[email protected] /]$ ssh-keygen -t ecdsa # -t 用来指定算法类型:ecdsa和dsa Generating public/private ecdsa key pair. Enter file in which to save the key (/home/zhangsan/.ssh/id_ecdsa): # 指定私钥位置 Cr

Android开发:本机Tomcat搭建服务器,客户端socket网络连接不上问题以及D-LINK端口转发设置

我是用自己的电脑搭建服务器,首先问题是我们需要在路由器上端口映射,外网才能访问到自己的电脑,如何端口映射可以看看这篇文章: http://blog.csdn.net/zhoubin1992/article/details/45917775 一.D-LINK端口转发设置 我的是D-link如图: 名称写你客户端的名称. IP地址:路由器给本机分配的IP地址,一般以192.168开头.查询方法:cmd下ipconfig 填写私有端口就是路由器需要打开的端口,也可以设置一个区间 公共端口的就是外网要访