TCP connect 的一个小问题?

TCP 客户端连接上  服务端后,服务端发送数据完毕, close(客户端fd); 这个时候 客户端在  connect 到服务端是否 OK (客户端 read 后调用 connect, 客户端没有调用 close) ?

答案是不可以:

errno = 106
ERROR connecting: Transport endpoint is already connected

测试代码如下:

svr

#include <stdio.h>  
#include <unistd.h>  
#include <errno.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <stdlib.h>  
#include <arpa/inet.h>  
#include <netinet/in.h>  

#define LY_ERR printf
void accept_handle(int connfd, struct sockaddr_in peeraddr);  

int main(int argc, const char *argv[])  
{  
    int        sockfd, connfd;  
    struct sockaddr_in  seraddr, peeraddr;  
    socklen_t  addrlen;  

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

    sockfd = socket(AF_INET, SOCK_STREAM, 0);  
    if (sockfd < 0) {  
        LY_ERR("socket: %s\n", strerror(errno));  
        return -1;  
    }  
   
    setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (int[]){1}, sizeof(int));


    seraddr.sin_family = AF_INET;  
    seraddr.sin_port = ntohs(atoi(argv[1]));  
    seraddr.sin_addr.s_addr = htonl(INADDR_ANY);  

    if (bind(sockfd, (struct sockaddr *)&seraddr, sizeof(struct sockaddr))) {  
        LY_ERR("bind: %s\n", strerror(errno));  
        return -1;  
    }  
   
    #define MAX_CONN (10)
    if (listen(sockfd, MAX_CONN) < 0) {  
        LY_ERR("listen: %s\n", strerror(errno));  
        return -1;  
    }  
#if 0 
    for (;;) {
        sleep(3);
        int n = send(sockfd, "123", sizeof("123"), 0);
        printf("n = %d\n", n);
    }
#endif
#if 1 
    addrlen = sizeof(struct sockaddr);  
    for (;;) {  
        connfd = accept(sockfd, (struct sockaddr *)(&peeraddr), &addrlen);  
        if (connfd < 0) {  
            LY_ERR("accept: %s\n", strerror(errno));  
            continue;  
        }  
        accept_handle(connfd, peeraddr);  
    }  
#endif
    return 0;  
}  

void accept_handle(int connfd, struct sockaddr_in peeraddr)  
{  
    char   buf1[32] = "Hello, welcome to server!";  
    char   buf[32]; 
    printf("Receive request from %s, port %d\n",  
            inet_ntop(AF_INET, &peeraddr.sin_addr, buf, sizeof(buf)),  
            ntohs(peeraddr.sin_port));  

    if (send(connfd, buf1, sizeof(buf1), 0) < 0) {  
        close(connfd);  
        return;  
    }  

    close(connfd);  
    //sleep(5);
}  

 

cli:

/* 
 *  * tcpclient.c - A simple TCP client
 *   * usage: tcpclient <host> <port>
 *    */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <errno.h>
#include <poll.h>

#define BUFSIZE 1024


/* 
 ** error - wrapper for perror
 **/
void error(char *msg) {
    perror(msg);
    exit(0);
}

int main(int argc, char **argv) 
{
    int sockfd, portno, n;
    struct sockaddr_in serveraddr, cli;
    struct hostent *server;
    char *hostname;
    char buf[BUFSIZE];

    /* check command line arguments */
    if (argc != 3) {
        fprintf(stderr,"usage: %s <hostname> <port>\n", argv[0]);
        exit(0);
    }

    hostname = argv[1];
    portno = atoi(argv[2]);

    /* socket: create the socket */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        error("ERROR opening socket");

    int enable = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
        error("setsockopt(SO_REUSEADDR) failed");
#if 1
    bzero((char *)&cli, sizeof(cli));
    cli.sin_family = AF_INET;  
    cli.sin_port = ntohs(3307);  
    cli.sin_addr.s_addr = htonl(INADDR_ANY);  
    /* 客户端也是可以调用 bind 的 */
    if (bind(sockfd, (struct sockaddr *)&cli, sizeof(struct sockaddr))) {   
        printf("bind: %s\n", strerror(errno));  
        return -1;  
    } 
#endif

#if 1
    server = gethostbyname(hostname);
    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host as %s\n", hostname);
        exit(0);
    }
#endif

    /* build the server's Internet address */
    bzero((char *) &serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    bcopy((char *)server->h_addr, 
            (char *)&serveraddr.sin_addr.s_addr, server->h_length);
    serveraddr.sin_port = htons(portno);


    /* connect: create a connection with the server */
    if (connect(sockfd, (const sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)  {
        printf("errno = %d\n", errno);
        error("ERROR connecting");
    }
    printf("conn success!");

    /* print the server's reply */
    bzero(buf, BUFSIZE);
    n = read(sockfd, buf, BUFSIZE);
    if (n < 0) { 
        error("ERROR reading from socket");
    }

    printf("Echo from server: %s, %d\n", buf, n);
    sleep(15);

    if (connect(sockfd, (const sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)  {
        printf("errno = %d\n", errno);
        error("ERROR connecting");
    }

    printf("conn success!");
    return 0;
}

 

输出:

./tcpsvr 10002
Receive request from 127.0.0.1, port 3307
Receive request from 127.0.0.1, port 3307


./tcpcli1 127.0.0.1 10002
conn success!Echo from server: Hello, welcome to server!, 32
errno = 106
ERROR connecting: Transport endpoint is already connected

 

转载于:https://my.oschina.net/tsh/blog/1439057

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值