kevent behavior with TCP socket
Denis Berezhnoy
denis.berezhnoy at gmail.com
Mon Aug 10 03:17:23 UTC 2009
Hi Adrian,
Thank for your answer! I checked that nobody listens for loopback address:
[denis at freebsd ~]$ sockstat -4
USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
denis sshd 95390 3 tcp4 192.168.1.103:22
192.168.11.26:53616
root sshd 95387 3 tcp4 192.168.1.103:22
192.168.11.26:53616
denis sshd 95324 3 tcp4 192.168.1.103:22
192.168.11.26:53608
root sshd 95321 3 tcp4 192.168.1.103:22
192.168.11.26:53608
root sshd 8149 4 tcp4 *:22 *:*
root inetd 870 5 tcp4 *:21 *:*
root inetd 870 6 tcp4 *:23 *:*
root sendmail 821 4 tcp4 127.0.0.1:25 *:*
root syslogd 689 7 udp4 *:514 *:*
[denis at freebsd ~]$
I printed out fflags. Here is the result:
Kevent event num 1 wait time 46
Event filter -2 flag 0 filter flags 0 data 43008
When I comment out the part of the code that listens socket then I have the
following output:
Kevent event num 1 wait time 23
Event filter -2 flag 32768 filter flags 61 data 32768
61 is ECONNREFUSED
And more when I make loopback address listening and try to connect it I
still get the same output:
Socket test start
Failed to connect with server 36
Kevent event num 1 wait time 23
Event filter -2 flag 0 filter flags 0 data 43008
Socket test end
but connection is actually accepted. I am totally confused here.
Best regards,
Denis
2009/8/9 Adrian Penisoara <ady at freebsd.ady.ro>
> Hi,
>
>
> On Sat, Aug 8, 2009 at 10:42 AM, Denis Berezhnoy <
> denis.berezhnoy at gmail.com> wrote:
>
>> Hi,
>>
>> Sorry for my previous post it was completely unclear I believe. Here is
>> problem description in pure C. Can you please take a look at the code
>> below:
>>
>> #include <netinet/in.h>
>> #include <sys/socket.h>
>> #include <sys/time.h>
>> #include <stdio.h>
>> #include <stdlib.h>
>> #include <string.h>
>> #include <fcntl.h>
>>
>> #include <sys/types.h>
>> #include <sys/event.h>
>> #include <sys/time.h>
>> #include <errno.h>
>>
>>
>>
>> int main(int argc, char *argv[])
>> {
>> struct sockaddr_in addr;
>> struct sockaddr_in addr2;
>>
>> int sd, cd, port, sRet;
>>
>> int sHandle;
>> int sEventNum = 0;
>>
>> struct kevent sChange;
>> struct kevent sEvent;
>>
>> struct timespec *sTimeoutPtr;
>> struct timespec sTimeout;
>>
>> struct timeval sTimeVal1 = {0,0};
>> struct timeval sTimeVal2 = {0,0};
>>
>> printf("Socket test start\n");
>>
>> sd = socket(PF_INET, SOCK_STREAM, 0);
>>
>> if ( sd < 0 )
>> {
>> printf("Server socket error\n");
>> return 0;
>> }
>>
>> port = htons(10000);
>>
>>
>> memset(&addr, 0, sizeof(addr));
>> addr.sin_family = AF_INET;
>> addr.sin_port = port;
>> addr.sin_addr.s_addr = htonl(INADDR_ANY);
>>
>> if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
>>
>> {
>> printf ("Server bind errror\n");
>> return 0;
>> }
>>
>>
>>
>> if ( listen(sd, 1) != 0 )
>> {
>> printf ("Server listen error \n");
>> return 0;
>> }
>>
>>
>> cd = socket(PF_INET, SOCK_STREAM, 0);
>>
>> if ( cd < 0 )
>> {
>> printf("Client socket error\n");
>> return 0;
>> }
>>
>> sRet = fcntl(cd, F_GETFL, 0);
>>
>> sRet |= O_NONBLOCK;
>>
>> sRet = fcntl(cd, F_SETFL, sRet);
>>
>> if (sRet < 0)
>> {
>> printf("can not set non block\n");
>> }
>>
>> port = htons(10000);
>>
>> memset(&addr2, 0, sizeof(addr2)); /* Clear struct */
>> addr2.sin_family = AF_INET; /* Internet/IP */
>> addr2.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* IP address */
>> addr2.sin_port = port; /* server port */
>>
>> /* Establish connection */
>>
>> if ((sRet = connect(cd,
>> (struct sockaddr *) &addr2,
>> sizeof(addr2))) < 0)
>> {
>>
>> printf("Failed to connect with server %d\n", errno);
>>
>> }
>>
>>
>> sHandle = kqueue();
>>
>>
>> if (sHandle == -1)
>> {
>> printf("Poll can not created queue\n");
>> }
>>
>> sTimeout.tv_sec = 0;
>> sTimeout.tv_nsec = 100000000;;
>>
>> EV_SET(&sChange, cd, EVFILT_WRITE, EV_ADD,0, 0, 0);
>>
>>
>> gettimeofday(&sTimeVal1, NULL);
>>
>> sEventNum = kevent(sHandle,
>> &sChange,
>> 1,
>> &sEvent,
>> 1,
>> &sTimeout);
>>
>> gettimeofday(&sTimeVal2, NULL);
>>
>> printf ("Kevent event num %d wait time %d \n", sEventNum,
>> sTimeVal2.tv_usec
>> - sTimeVal1.tv_usec);
>>
>> if (sEventNum == 1)
>> {
>> printf ("Event filter %d flag %d data %d \n", sEvent.filter, sEvent.flags,
>> sEvent.data);
>> }
>>
>> close(sHandle);
>>
>> close(cd);
>>
>> close(sd);
>>
>> printf("Socket test end\n");
>> }
>>
>> Program output
>>
>> Socket test start
>> Failed to connect with server 36
>> Kevent event num 1 wait time 26
>> Event filter -2 flag 0 data 43008
>> Socket test end
>>
>> The question is why kevent returns 1 event when server does not accept
>> connections from clients.
>>
>
> Question: is there something listening on your loopback address
> (127.0.0.1) or all addresses at port 10000 (sockstat -4 output should be
> evident) ? If not, have you also tested with something listening on that
> address ?
>
> If there is nothing to connect onto the loopback address then the
> connection will immediately fail. Then I believe kevent should return with a
> failure filter flag set.
>
> One problem I see is that you are checking the action flags
> (kevent.flags) instead of the filter flags (kevent.fflags). Please re-run
> checking the sEvent.fflags field and compare with values in <sys/event.h>
> and let us/me know what do you get.
>
> Regards,
> Adrian Penisoara
> EnterpriseBSD
>
More information about the freebsd-net
mailing list