免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4779 | 回复: 13
打印 上一主题 下一主题

socket绑定问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-03-29 12:02 |只看该作者 |倒序浏览
在用Socket监听的时候想实现循环监听,直到收到特定的字符才终止,核心程序代码如下:

#define SIZE 1024
#define TIME_PORT  1313

char buf[SIZE];

int main(int argc, char *argv[])
{
          int len, sockfd, client_sockfd, buflen;
          int nread;
          char *halt="halt";
          struct sockaddr_in serv_addr, client_addr;
          time_t t;
          struct tm *stmp;
        do{
           if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
           { perror(NULL); exit(2); }
           serv_addr.sin_family = AF_INET;
           serv_addr.sin_addr.s_addr = INADDR_ANY;
           serv_addr.sin_port = htons(TIME_PORT);
           bzero(&(serv_addr.sin_zero),;
           t=bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr_in));
          if (t == -1) { printf("Bind not successful\n"; exit(0); }
          printf("bind was successful\n";
         len = sizeof(struct sockaddr_in);
         listen(sockfd, 5);
         printf("listen was successful\n";
         client_sockfd = accept(sockfd, (void *)&client_addr, &len);
         printf("connection made - client sockfd is %d\n",client_sockfd);
         printf("Request from %s port %d\n",inet_ntoa(client_addr.sin_addr),
         ntohs(client_addr.sin_port));
         buflen = read(client_sockfd,&buf,SIZE);
         write(1,buf, buflen);
         printf("\n";
        close(client_sockfd);
        close(sockfd);

        }  while(strcmp(buf,halt)!=0);}
重点就是红色标注的do... while循环。在执行第一次接收到字符的时候没有问题,但是在第二次循环中出错,打印错误即蓝色标注部分:“Bind not successful”。
不知道是什么原因?应该说第一次打开之后又关闭了,可是再循环为什么出错?

另外,即使不循环,在程序执行完一次后,接着再执行的时候也会出现“Bind not successful”的错误,过一两分钟就可以再正常执行,这个也是socket榜定的问题,搞不清楚怎么回事。请大虾指点

论坛徽章:
0
2 [报告]
发表于 2005-03-29 12:24 |只看该作者

socket绑定问题

你把循环去了
你的循环体有问题

论坛徽章:
0
3 [报告]
发表于 2005-03-29 12:26 |只看该作者

socket绑定问题

呵呵,我估计你的问题跟我昨天问的问题是同一个问题……
我的问题是“TIME_WAIT状态是每次时间都一样长么? ”,关于listen端口重启的问题

估计你bind失败的时候,该端口应该处于TIME_WAIT状态,用netstat查查看。
这个状态1,2分之后会过去,那之后才会再次成功。

narkissos给我的方案是用setsockopt,我还没试……
呵呵,一起学习学习吧

论坛徽章:
0
4 [报告]
发表于 2005-03-29 12:27 |只看该作者

socket绑定问题

循环监听干什么用?

论坛徽章:
0
5 [报告]
发表于 2005-03-29 12:32 |只看该作者

socket绑定问题

我面试写的程序,希望能帮上点忙
/*  For this example, server.c,
    we call fork() to deal with more clients in a time,
    if we deal with client one by one,then every 2 senconds deal with one client;
    client will send ABC ; we echo with BCD  */

#include <sys/types.h>;
#include <sys/socket.h>;
#include <stdio.h>;
#include <netinet/in.h>;
#include <sys/time.h>;
#include <sys/ioctl.h>;
#include <unistd.h>;

int main()
{
    int server_sockfd, client_sockfd;
    int server_len, client_len;
    struct sockaddr_in server_address;
    struct sockaddr_in client_address;
    int result,pid;
    fd_set readfds, testfds;

/*  Create and name a socket for the server.  */

    server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(9734);
    server_len = sizeof(server_address);

    bind(server_sockfd, (struct sockaddr *)&server_address, server_len);

/*  Create a connection queue and initialize readfds to handle input from server_sockfd.  */

    listen(server_sockfd, 5);

    FD_ZERO(&readfds);
    FD_SET(server_sockfd, &readfds);

/*  Now wait for clients and requests.
    Since we have passed a null pointer as the timeout parameter, no timeout will occur.
    The program will exit and report an error if select returns a value of less than 1.  */

    while(1) {
        char ch;
        int fd;
        int nread;

        testfds = readfds;

        printf("server waiting\n";
        result = select(FD_SETSIZE, &testfds, (fd_set *)0,
            (fd_set *)0, (struct timeval *) 0);

        if(result < 1) {
            perror("server";
            exit(1);
        }

/*  Once we know we've got activity,
    we find which descriptor it's on by checking each in turn using FD_ISSET.  */

        for(fd = 0; fd < FD_SETSIZE; fd++) {
            if(FD_ISSET(fd,&testfds)) {

/*  If the activity is on server_sockfd, it must be a request for a new connection
    and we add the associated client_sockfd to the descriptor set.  */

                if(fd == server_sockfd) {
                    client_len = sizeof(client_address);
                    client_sockfd = accept(server_sockfd,
                        (struct sockaddr *)&client_address, &client_len);
/*if  create process faild;drop*/
                        if((pid=fork())==-1)
                        {
                                close(client_sockfd);
                                continue;
                        }
                        else if(pid>;0)
                        /*father process*/
                        {
                                close(client_sockfd);
                                continue;
                        }
                                else
                                /*child */
                                {
                                            FD_SET(client_sockfd, &readfds);
                                            printf("adding client on fd %d\n", client_sockfd);
                                }
                }

/*  If it isn't the server, it must be client activity.
    If close is received, the client has gone away and we remove it from the descriptor set.
    Otherwise, we 'serve' the client as in the previous examples.  */

                else {
                    ioctl(fd, FIONREAD, &nread);

                    if(nread == 0) {
                        close(fd);
                        FD_CLR(fd, &readfds);
                        printf("removing client on fd %d\n", fd);
                    }

                    else {
                        read(fd, &ch, 1);
                        sleep(2);
                        printf("serving client on fd %d\n", fd);
                        ch++;
                        write(fd, &ch, 1);
                    }
                }
            }
        }
    }
}





*  Make the necessary includes and set up the variables.  */

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

int main()
{
    int sockfd;
    int len;
    struct sockaddr_in address;
    int result;
    char ch = 'A';

/*  Create a socket for the client.  */

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

/*  Name the socket, as agreed with the server.  */

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr("127.0.0.1";
    address.sin_port = htons(9734);
    len = sizeof(address);

/*  Now connect our socket to the server's socket.  */

    result = connect(sockfd, (struct sockaddr *)&address, len);

    if(result == -1) {
        perror("oops: client";
        exit(1);
    }

/*  We can now read/write via sockfd.  */

    write(sockfd, &ch, 1);
    read(sockfd, &ch, 1);
    printf("char from server = %c\n", ch);
    close(sockfd);
    exit(0);
}

论坛徽章:
0
6 [报告]
发表于 2005-03-29 13:14 |只看该作者

socket绑定问题

楼,楼主,我的问题已经解决了
就是在bind之前用setsockopt把socket属性改成SO_REUSEADDR就可以了

但你的问题还有一点点不一样,我的是手动的重启,而你的for如果在TIME_WAIT期间(1,2分钟)内循环了很多次的话,可能会有好多socket处在TIME_WAIT状态(倒是应该不会出什么太大的差错,因为他们会在TIME_WAIT过去后自动消失),呵呵

论坛徽章:
0
7 [报告]
发表于 2005-03-29 14:03 |只看该作者

socket绑定问题

吃完午饭回来,发现有这么多回复,先谢谢各位的贴子

我想我的问题应该跟ukin50说的差不多。主要问题是端口第一次可以绑定监听,但如果把它close掉以后,在一两分钟内无法再执行。

ukin50和surfzsl都提出了解决方法,我试一下,再给大家通报结果。

另外说一下这个程序的目的兼答yeath的提问:

主要目的是实现两台机器之间的通讯。Server负责监听,Client负责发送消息。循环的目的是为了让Server端一直监听,如果Client端不发送特定的数据就不结束,例如直到Client发送halt给Server,Server才终止,跳出循环。

论坛徽章:
0
8 [报告]
发表于 2005-03-29 14:11 |只看该作者

socket绑定问题

那干吗要循环创建socket
。。。

论坛徽章:
0
9 [报告]
发表于 2005-03-29 14:16 |只看该作者

socket绑定问题

偶比较菜,刚学socket编程。
可能比较土。。。
看到socket的监听程序,感觉可以这样实现,就编了程序来试。
有什么好的方法可以实现偶上面所说的?

论坛徽章:
0
10 [报告]
发表于 2005-03-29 14:27 |只看该作者

socket绑定问题

监听一次就可以了
然后就接受或发送数据
。。。。。
好象不能连续创建那么多相同的socket吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP