Thread: accept() and WSAEFAULT

  1. #1
    Registered User
    Join Date
    Jan 2006
    Location
    Europe/Belgrade
    Posts
    78

    accept() and WSAEFAULT

    Hi,
    I am trying to make an echo server under Windows similar as one under Linux.
    Code:
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
     
    #pragma comment (lib, "ws2_32.lib")
    #pragma comment (lib, "mswsock.lib")
    #pragma comment (lib, "advapi32.lib")
     
     
    fd_set fds_dup(fd_set* src)
    {
    	unsigned i;
    	fd_set src_copy;
    	FD_ZERO(&src_copy);
     
    	src_copy.fd_count = src->fd_count;
    	for (i = 0; i < src_copy.fd_count; ++i)
    		src_copy.fd_array[i] = src->fd_array[i];
    	return src_copy;
    }
     
     
    int main()
    {
    	WSADATA wsaData;
    	SOCKET server_sock;
    	const char* server_address_s = "localhost";
    	const char* PORT = "7000";
    	struct addrinfo* server_address;
    	BOOL opt_val = FALSE;
    	const unsigned int PENDING_SIZE = 5;
    	fd_set read_fds;
    	struct addrinfo hint;
    	const struct timeval timeout = {1, 0};
     
    	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
    	{
    		fprintf(stderr, "main(): error calling 'WSAStartup()'");
    		WSACleanup();
    		exit(EXIT_FAILURE);
    	}
     
    	hint.ai_family = 0;
    	hint.ai_socktype = SOCK_STREAM;
    	hint.ai_flags = AI_PASSIVE;
    	hint.ai_protocol = 0;
    	hint.ai_addrlen = 0;
    	hint.ai_canonname = NULL;
    	hint.ai_addr = NULL;
    	hint.ai_next = NULL;
     
    	if (getaddrinfo(server_address_s, PORT, &hint, &server_address) != 0)
    	{
    		printf("main(): cannot locate host, error code=%ld, exiting program\n", WSAGetLastError());
    		WSACleanup();
    		exit(EXIT_FAILURE);
    	}
     
    	server_sock = socket(server_address->ai_family, server_address->ai_socktype, server_address->ai_protocol);
    	if (server_sock == INVALID_SOCKET)
    	{
    		fprintf(stderr, "main(): cannot create socket, error code=%ld, exiting program\n", WSAGetLastError());
    		WSACleanup();
    		exit(EXIT_FAILURE);
    	}
     
    	setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&opt_val, sizeof(int));
    	if (bind(server_sock, server_address->ai_addr, server_address->ai_addrlen) == SOCKET_ERROR)
    	{
    		printf("main(): cannot bind, error code=%ld, exiting program\n", WSAGetLastError());
    		WSACleanup();
    		exit(EXIT_FAILURE);
    	}
     
    	freeaddrinfo(server_address);
     
    	if (listen(server_sock, PENDING_SIZE) == SOCKET_ERROR)
    	{
    		printf("main(): cannot listen, error code=%ld, exiting program\n", WSAGetLastError());
    		WSACleanup();
    		exit(EXIT_FAILURE);
    	}
     
    	FD_ZERO(&read_fds);
    	FD_SET(server_sock, &read_fds);
     
    	while (1)
    	{
    		unsigned i;
    		int nfds;
    		fd_set read_fds_copy;
     
     
    		FD_ZERO(&read_fds_copy);
    		read_fds_copy = fds_dup(&read_fds);
     
    		printf("main(): while...\n");
    		nfds = select(0, &read_fds_copy, NULL, NULL, NULL);
    		if (nfds == SOCKET_ERROR)
    		{
    			printf("main(): error calling 'select()', exiting program\n");
    			WSACleanup();
    			exit(EXIT_FAILURE);
    		}
    		else if (nfds == 0)
    		{
    			printf("main(): select time limit expired\n");
    			continue;
    		}
     
    		for (i = 0; i < read_fds_copy.fd_count; ++i)
    		{
    			SOCKET sock = read_fds_copy.fd_array[i];
    			if (sock == server_sock)
    			{
    					// new client accepted
     
    					struct sockaddr_in client_address;
    					socklen_t client_address_len = sizeof(struct sockaddr);
    					SOCKET client_sock;
    					char addr_buf[1000];
    					const char* client_address_s;
     
    					client_sock = accept(server_sock, (struct sockaddr*)&client_address, &client_address_len);
    					//client_sock = accept(server_sock, NULL, NULL);
    					if (client_sock == INVALID_SOCKET)
    					{
    						printf("main(): cannot accept client, error code=%ld, sleeping\n", WSAGetLastError());
    						Sleep(1000);
    						continue;
    					}
    					printf("main(): client accepted...\n");
     
    					client_address_s = inet_ntop(AF_INET, &client_address, addr_buf, INET_ADDRSTRLEN);
    					if (client_address_s == NULL)
    						printf("main(): cannot read client address\n");
    					else
    						printf("main(): client accepted from %s\n", client_address_s);
     
    					FD_SET(client_sock, &read_fds);
    			}
    			else
    			{
    				// client request
     
    				const int REQUEST_LEN = 1000;
    				char request[1000];
    				int result;
     
    				memset(request, '\0', REQUEST_LEN);
    				result = recv(sock, request, REQUEST_LEN, 0);
    				if (result == SOCKET_ERROR)
    				{
    					// no request from client
     
    					printf("main(): cannot receive request\n");
    					closesocket(sock);
    					FD_CLR(sock, &read_fds);
    					continue;
    				}
    				else if (result == 0)
    				{
    					// client closed
     
    					printf("main(): client closed\n");
    					closesocket(sock);
    					FD_CLR(sock, &read_fds);
    					continue;
    				}
    				else
    				{
    					// echo client's request
     
    					printf("main(): request=%s\n", request);
    					result = send(sock, request, strlen(request), 0);
    					if (result == SOCKET_ERROR)
    					{
    						fprintf(stderr, "main(): cannot send response\n");
    						closesocket(sock);
    						FD_CLR(sock, &read_fds);
    						continue;
    					}
    					printf("main(): echo sent\n");
    				}
    			}
    		}	
    	}
     
    	WSACleanup();
    	return EXIT_SUCCESS;
    }
    If I put a line
    Code:
    client_sock = accept(server_sock, NULL, NULL);
    everything works fine, but if I put
    Code:
    client_sock = accept(server_sock, (struct sockaddr*)&client_address, &client_address_len);
    I get the error 10014. MSDN says that The addrlen parameter is too small or addr is not a valid part of the user address space, but I find that this is not a case, since client_address and client_address_len are initialized. Any ideas?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    accept function

    But you have
    struct sockaddr_in client_address;

    And then inconsistently, say the size for something else.
    socklen_t client_address_len = sizeof(struct sockaddr);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jan 2006
    Location
    Europe/Belgrade
    Posts
    78
    That's because client_address is casted into (struct sockaddr*). I get the same issue no matter if I put
    Code:
    socklen_t client_address_len = sizeof(struct sockaddr);
    client_sock = accept(server_sock, (struct sockaddr*)&client_address, &client_address_len);
    or
    Code:
    socklen_t client_address_len = sizeof(struct sockaddr_in);
    client_sock = accept(server_sock, (struct sockaddr*)&client_address, &client_address_len);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. accept() within FreeBSD 8
    By karas in forum Networking/Device Communication
    Replies: 0
    Last Post: 10-26-2010, 07:01 AM
  2. accept()
    By ~Kyo~ in forum Networking/Device Communication
    Replies: 11
    Last Post: 11-28-2009, 08:57 PM
  3. How can i accept any connection
    By lolguy in forum Networking/Device Communication
    Replies: 2
    Last Post: 04-06-2009, 02:51 PM
  4. Error with accept();
    By xddxogm3 in forum Networking/Device Communication
    Replies: 35
    Last Post: 08-19-2005, 08:32 PM
  5. accept()
    By char in forum C Programming
    Replies: 0
    Last Post: 05-30-2002, 02:22 PM