Я использую Visual Studio Enterprise 2017 на DELL E6400 с Windows 10. Я пишу функцию для работы в качестве сервера.У меня проблемы с принятием соединения после обслуживания соединения один раз.Я закрыл предыдущее соединение.Я использовал Wireshark и вижу SYN, SYN / ACK, ACK, поэтому логическое соединение установлено.Но моя программа не выходит из вызова select (обратите внимание, что первый раз проходит гладко, и эта проблема возникает после того, как я закрыл первое соединение).
Вот суть последовательности кода "()"означает, что это вызов функции:
gethostname()
gethostbyaddr()
server_addr->sin_family
server_addr->sin_port
socket()
setsockopt()
bind()
getsockname()
listen()
FD_ZERO();
FD_SET();
k = select()
closesocket()
Вот фактический код:
#include <stdlib.h>
#include <conio.h>
#include "EasyTcp.h"
// On Windows, use Ws2_32.dll
/* need to define some linux-only symbols for other systems */
#ifndef SOL_TCP
#ifndef IPPROTO_TCP
#define IPPROTO_TCP 6 // 6 usually = TCP
#endif
#define SOL_TCP IPPROTO_TCP /* tcp's protocol number (from /etc/protocols) */
#endif
#define LISTENING_DEPTH 3
#define MAXHOSTNAMELEN 132
void start_up(void);
SOCKET openserver( unsigned int server_port, char *server_name,
struct sockaddr_in *server_addr );
int print_address(char *message, int len, struct sockaddr_in *addr,
unsigned int *host, unsigned int *port);
int print_ip_address( unsigned int ip_address );
SOCKET get_local_address( SOCKET fd, unsigned int *host, unsigned int *port);
int get_ip_address( char *name, unsigned int *host );
SOCKET accept_a_client(SOCKET listening_fd, struct sockaddr_in *addr,
unsigned int *whole, unsigned int *fraction);
/* Accept a connection on port local_port.
Returns the socket or -1 if an error.
*/
SOCKET EasyAccept( int local_port )
{
SOCKET listening_fd = -1; // -1 when not connected
SOCKET fd;
unsigned int sys_remote_port = 0;
unsigned int sys_local_host = 0;
unsigned int sys_remote_host = 0;
struct sockaddr_in target_addr;
struct sockaddr_in initiator_addr;
unsigned int sys_local_port = local_port; // The port to listen on
unsigned int *whole_ptr = NULL, *fraction_ptr = NULL; // The amount of time to listen
char *default_host = NULL; // The host you want to listen to, else NULL
listening_fd = openserver( sys_local_port, default_host, &target_addr );
if( listening_fd >= 0 )
{
print_address("Listening", 1, &target_addr, &sys_local_host,
&sys_local_port);
}
else
{
printf("openserver returned an error\n");
return -1;
}
if( (fd = accept_a_client(listening_fd, &initiator_addr,
whole_ptr,fraction_ptr)) >= 0 )
{/* accept succeeded, fd is connection to new initiator */
print_address("Server", 1, &initiator_addr, &sys_remote_host,
&sys_remote_port);
get_local_address(fd, &sys_local_host, &sys_local_port);
}
else
{/* accept failed */
printf("accept failed, fd=%p\n", (void *)fd);
return -1;
}
return fd;
}
int EasyConnect( int remote_port, char *remote_server )
{
// not done yet
printf("EasyConnect() is not finished\n");
_getch();
exit(1);
}
/* Opens a new TCP socket for the server at interface server_name, */
/* port server_port. Returns in server_addr the server's internet */
/* address structure. The server is NOT connected to a client on return. */
/* Returns an fd that is a "listening post" on which to make connections. */
SOCKET openserver( unsigned int server_port, char *server_name,
struct sockaddr_in *server_addr )
{
int len;
SOCKET fd;
struct sockaddr_in address1;
struct in_addr address0;
struct hostent *node_ptr;
char local_node[MAXHOSTNAMELEN];
char *host_name;
char buffer[64];
start_up();
/* get the internet name of the local host node on which we are running */
if( gethostname(local_node, MAXHOSTNAMELEN) < 0 )
{
printf("openserver gethostname: %s\n", strerror(errno));
strcpy(local_node, "Unknown Host");
}
if( server_name == NULL )
host_name = local_node; /* default to local node */
else
host_name = server_name;
/* get structure for local interface server is to use */
if( isdigit((int)host_name[0]) )
{/* must be an ip address, not a DNS name */
#ifdef __sun__
if( (*((int *)&address0) = inet_addr(host_name)) == -1 )
#else
if( !inet_aton(host_name, &address0) )
#endif
{
printf("Invalid IP address \"%s\"\n", host_name);
return -1;
}
if( (node_ptr = gethostbyaddr((char *)&address0,
sizeof(address0), AF_INET)) == NULL )
{
herror(host_name);
return -1;
}
}
else if( (node_ptr = gethostbyname(host_name)) == NULL )
{
herror(host_name);
return -1;
}
/* set up Internet address structure for the server */
if (server_addr == NULL) /* user doesn't want this back */
{
server_addr = &address1; /* so store it locally */
}
memset(server_addr, 0, sizeof(struct sockaddr_in));
server_addr->sin_family = AF_INET; // node_ptr->h_addrtype; /* should be AF_INET */
server_addr->sin_port = htons( (u_short)server_port );
if( server_name == NULL )
server_addr->sin_addr.s_addr=htonl(INADDR_ANY); /* use any interface */
else
memcpy(&server_addr->sin_addr, node_ptr->h_addr, node_ptr->h_length);
/* open an internet TCP socket */
if( (fd = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
{
printf("openserver socket: %s\n", strerror(errno));
return -1;
}
/* set this socket to reuse port addresses quickly */
if (setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, buffer, sizeof( buffer ) ) < 0)
{
printf( "openserver setsockopt REUSEADDR: %s\n", strerror( errno ) );
}
/* bind this socket to the server's Internet address */
if( bind(fd,(struct sockaddr *)server_addr,sizeof(struct sockaddr_in))<0 )
{
printf("Bind of IP address %s returned an error, port %d: %s\n",
inet_ntoa(server_addr->sin_addr), ntohs(server_addr->sin_port),
strerror(errno));
//close(fd);
return -1;
}
/* now find out what local port number was assigned to this server */
len = sizeof(struct sockaddr);
if( getsockname(fd, (struct sockaddr *)server_addr, (void *)&len) < 0 )
{
printf("openserver getsockname: %s\n", strerror(errno));
close(fd);
return -1;
}
/* set up listening backlog for connect requests from clients */
if( listen(fd, LISTENING_DEPTH) < 0 )
{
printf("openserver listen: %s\n", strerror(errno));
close(fd);
return -1;
}
/* we are now successfully established as a server */
return fd; /* return fd of listening socket */
}
int print_address(char *message, int len, struct sockaddr_in *addr,
unsigned int *host, unsigned int *port)
{
printf("%*s at IP address %s, port %d\n",
len, message, addr->sin_addr.S_un.S_addr == 0 ? "any" : inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
if( host != NULL )
*host = ntohl(addr->sin_addr.s_addr);
if( port != NULL )
*port = ntohs(addr->sin_port);
return 0;
}
int print_ip_address( unsigned int ip_address )
{
struct sockaddr_in x;
x.sin_addr.s_addr = htonl(ip_address);
printf("%s", inet_ntoa(x.sin_addr));
return 0;
}
SOCKET get_local_address( SOCKET fd, unsigned int *host, unsigned int *port)
{
#if defined(__osf__) || defined(_HPUX_SOURCE)
struct sockaddr_in addr;
int n = sizeof(addr);
#else
struct sockaddr_in addr;
int n = sizeof(addr);
#endif
if( getsockname(fd, (struct sockaddr *)&addr, &n) < 0 )
{
perror("getsockname");
return -1;
}
if( host != NULL )
*host = ntohl(addr.sin_addr.s_addr);
if( port != NULL )
*port = ntohs(addr.sin_port);
return 0;
}
int get_ip_address( char *name, unsigned int *host )
{
struct in_addr address0;
struct hostent *node_ptr;
/* get structure for remote host node on which server resides */
if( isdigit((int)name[0]) )
{/* must be an ip address, not a DNS name */
#ifdef __sun__
if( (*((int *)&address0) = inet_addr(name)) == -1 )
#else
if( !inet_aton(name, &address0) )
#endif
{
printf("Invalid IP address \"%s\"\n", name);
return -1;
}
if( (node_ptr = gethostbyaddr((char *)&address0,
sizeof(address0), AF_INET)) == NULL )
{
herror(name);
return -1;
}
}
else if( (node_ptr = gethostbyname(name)) == NULL )
{
herror(name);
return -1;
}
if( host != NULL )
*host = ntohl(*(unsigned int *)node_ptr->h_addr);
return 0;
}
/* wait for at most whole.fraction seconds to accept a connection */
/* returns fd >= 0 if ok, -1 on error, -2 on timeout or control-C */
SOCKET accept_a_client( SOCKET listening_fd, struct sockaddr_in *addr,
unsigned int *whole, unsigned int *fraction )
{
struct sockaddr *client;
struct sockaddr local_addr;
int len, k;
SOCKET fd;
struct timeval local_tv, *tv;
fd_set readset;
char buffer[64];
len = sizeof(struct sockaddr);
if( addr == NULL )
client = &local_addr;
else
client = (struct sockaddr *)addr;
//printf("Accepting connection\n");
fflush(stdout);
do {
if( whole == NULL || fraction == NULL )
tv = NULL; /* no timeout given */
else
{/* have a timeout, must set it up each time around loop */
tv = &local_tv;
tv->tv_sec = *whole;
tv->tv_usec = *fraction;
}
FD_ZERO(&readset);
FD_SET(listening_fd, &readset);
k = select(0, &readset, NULL, NULL, tv); // for Windows the 1st parameter is not used
if( k < 0 )
{/* select found an error */
if( errno == EINTR )
{/* return forced by control-C, treat it like timeout */
return -2;
}
else
{
printf("Select on fd %p: %s\n", (void *)listening_fd, strerror(errno));
return -1;
}
}
else if( k == 0 )
{/* select timed out */
return -2;
}
else if( (fd = accept(listening_fd, client, (void *)&len)) < 0 )
{/* accept found an error */
if( errno == EINTR )
return -2;
else
{
printf("Accept on fd %p: %s\n", (void *)listening_fd, strerror(errno));
return -1;
}
}
else
{/* fd is now the newly accepted connection from a new client */
/* turn off the Nagle Algorithm on this connection */
if( setsockopt(fd, SOL_TCP, TCP_NODELAY, buffer, sizeof(buffer)) < 0 )
{
printf("accept_a_client setsockopt NODELAY: %s\n",
strerror(errno));
}
break;
}
}
while( 1 );
/*****
printf("accept_a_client returning fd %p\n", fd);
*****/
return fd;
}