连接到套接字拒绝

时间:2015-12-28 13:20:52

标签: c linux sockets

我有简单的TCP服务器程序。在我使用CTRL+C关闭它并在某些情况下再次重新启动后,telnet客户端报告我"connection refused"。为什么不总是这样,但在某些情况下呢?命令ps没有显示我的程序。

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include<string.h>

void printHex(char *bts);

int main() {
    char str[100];
    int listen_fd, comm_fd;
    struct sockaddr_in servaddr;
    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    bzero( &servaddr, sizeof(servaddr));

    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htons(INADDR_ANY);
    servaddr.sin_port = htons(22000);
    printf("binding\n");
    bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));

    printf("listening\n");
    listen(listen_fd, 10);

    printf("accepting\n");    
    comm_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
    printf("accep done\n");

    int cn = 0;

    while(1) {
        bzero(str, 100);
        printf("will read\n");
        int br = read(comm_fd, str, 100);
        printf("read done\n");
        if (br > 0) {
            printHex(str);
        } else if (br <= 0) {
            comm_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
            printf("accep done\n");
        }
        printf("error %d \n", br);
   }
}

void printHex(char *bts) {
    char *s = bts;
    int i = 0;
    do {
        printf("%02X ", (unsigned char) *bts);
    } while (*++bts !=0);
    printf("%s\n",s);
}

3 个答案:

答案 0 :(得分:1)

您应该检查系统调用的所有返回值:

int res;

res = bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
if (res == -1)
  // handle error
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listed_fd == -1)
  // handle error

您很可能会发现您的代码在bind系统调用中失败,这意味着您无法在相同的IP地址,协议和端口上重用套接字。您可以使用setsockopt调用

更改此设置
// allow to rebind
int reuseaddr_on = 1;
res = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR,
            &reuseaddr_on, sizeof(reuseaddr_on));              
if (res < 0)
{
    stderr("Setting of SO_REUSEADDR on server's"     
                            "socket failed");                         
}

完成后,您还应该关闭套接字。

while(1)
{
  //  your loop
}
res = close(comm_fd);
if (res == -1)
  // handle error

正如Linux程序员手册在致电近距离呼叫的网页上所说:

  

注意

     

不检查close()的返回值是一个常见但严重的编程错误。很有可能   先前write(2)操作的错误首先在最后的close()处报告。关闭文件时不检查返回值可能会导致静默   失去了          数据

答案 1 :(得分:0)

始终检查系统调用的返回值。 在这种情况下,

    bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));

EADDRINUSE失败,因为在绑定之前没有在套接字上设置SO_REUSEADDR

答案 2 :(得分:0)

当您执行CTRL-C并重新启动时,绑定是否成功?

bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));

您需要检查bind call的状态。很可能由于连接已在服务器中移至TIME_WAIT状态而失败。从此,客户端出现“连接被拒绝”的错误。

bind之后立即运行服务器时,CTRL-C要成功,请使用套接字选项中的SO_REUSEADDR。只要没有另一个程序绑定到端口,这个bind就会成功。