twfx
twfx

Reputation: 1694

tcp server does not return from accept()

I am trying out with a TCP server/client program, and wonder why at server side, the program loop at accept() ....

My idea is to develop a TCP server which receive 1 request at a time from multiple clients. The connection between server and client shall close upon completing single operation. For eg 1) The TCP server shall be hearing port 30000 at all time. 2) TCP client 1 connect to TCP server, send "hello", and wait for "hello" feedback from server, and close the connection. 3) TCP client 2 connect to TCP server, send "hello", and wait for "hello" feedback from server, and close the connection. and so on until TCP client n....

All of the operation above is executed one at a time, meaning TCP client 1 and 2 will not send message to TCP server at the same time, and, once TCP client 1 complete the operation it will not connect to server anymore (if necessary, a new connection can be triggered).

the output shows

======== NW Test =======
1) Start (T)CP Server
2) Start T(C)P  Client
3) (S)end TCP Message
4) Close TCP S(O)cket
0) (Q)uit
================================
Option: t
Starting TCP server...
create socket success.
bind socket success.
listen socket success.

I am expecting also...

accept socket success.
pthread_create success.
TCP server started, listening socket [tcpsocket]

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

struct attr {
  int tcpsocket;
};

static int nwMenu();
static void *event_start(void* param);

int tcpserver(){
    int thread_id;
    int tcpSocket;
    int listenSocket;
int nRet;
    socklen_t nLen;        
struct attr atr;
    struct sockaddr_in saTCPServer, saTCPClient;

fprintf(stderr, "Starting TCP server...\n");

    listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (listenSocket < 0)
    {
  fprintf(stderr, "fail to create socket.\n");
      return -1;
    } else {
  fprintf(stderr, "create socket success.\n");
}

    saTCPServer.sin_family = AF_INET;
    saTCPServer.sin_addr.s_addr = INADDR_ANY;
    saTCPServer.sin_port = 30000;

    nRet = bind(listenSocket, (struct sockaddr *) &saTCPServer, sizeof(struct sockaddr));
    if (nRet < 0)
    {
  fprintf(stderr, "fail to bind socket.\n");
      close (listenSocket);
      return -1;
    } else {
  fprintf(stderr, "bind socket success.\n");
}

    if (listen(listenSocket, 5) < 0) {
   fprintf(stderr, "fail to listen socket.\n"); 
       close (listenSocket);
       return -1;
    } else {
  fprintf(stderr, "listen socket success.\n");
}

    nLen = sizeof(saTCPClient);

    tcpSocket = accept(listenSocket, (struct sockaddr *) &saTCPClient,  &nLen);
    if (tcpSocket < 0)
    {      
  fprintf(stderr, "fail to accept socket.\n");
      close (listenSocket);
      return -1;      
    }  else {
  fprintf(stderr, "accept socket success.\n");
}
atr.tcpsocket = tcpSocket;

    close (listenSocket); 

    if(pthread_create(&thread_id, NULL, (void*) event_start, (void*) &atr) != 0){
    fprintf(stderr, "pthread_create failed.\n");
} else {
  fprintf(stderr, "pthread_create success.\n");
};

fprintf(stderr, "TCP server started, listening socket %d\n", tcpSocket);

return 0;

}

static void *event_start(void* param) {

    int quit = 0;
    int nRet = 0;
int tcpSocket;
    char szBuf[4096];

struct attr *p_atr = (struct attr* )param;
tcpSocket = p_atr->tcpsocket;

    while (!quit){

        nRet = recv(tcpSocket, szBuf, sizeof(szBuf), 0);
        if (nRet <= 0 ) // peer closed
         {
            fprintf(stderr, "receiver quit recv\n");
        quit = 1;
        break;
          }

        fprintf(stderr, "recv: %s\n", szBuf);

        send(tcpSocket, szBuf, sizeof(szBuf), 0);
    }

     close(tcpSocket);
}


int tcpclient(){
    int tcpSocket;
    struct sockaddr_in saTCPServer;

    bzero((void *) &saTCPServer, sizeof(saTCPServer));

    char* szServer = "127.0.0.1";
    int nPort = 30000;

    inet_aton(szServer, &saTCPServer.sin_addr);

    tcpSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (tcpSocket < 0){
        return -1;
    } else {
        fprintf(stderr, "client tcp socket: %d\n", tcpSocket);
    }

    saTCPServer.sin_family = AF_INET;
    saTCPServer.sin_port = htons(nPort);

    if (connect(tcpSocket, (struct sockaddr *) &saTCPServer, sizeof(saTCPServer)) < 0 )     {
        return -1;
    }

    fprintf(stderr, "TCP client started, listening socket %d\n", tcpSocket);

    return 0;
}

int send_tcp_msg(int tcpSocket){
    int nRet;
    char szBuf[4096];

    memset(szBuf, 0x00, sizeof(szBuf));

    send(tcpSocket, "hello", sizeof("hello"), 0);

    nRet = recv(tcpSocket, szBuf, sizeof(szBuf), 0);

    fprintf(stderr, "recv: %s\n", szBuf);

return 0;
}

int close_tcp(int tcpSocket){
    close(tcpSocket);

return 0;
}    

static int nwMenu(){
    int ret = 0;
    int socket;
    char buff[1024];

    do{
    fprintf(stderr, "======== NW Test =======\n");
    fprintf(stderr, "1) Start (T)CP Server\n");
    fprintf(stderr, "2) Start T(C)P  Client\n");
    fprintf(stderr, "3) (S)end TCP Message\n");
    fprintf(stderr, "4) Close TCP S(O)cket\n");     
    fprintf(stderr, "0) (Q)uit\n"); 
    fprintf(stderr, "================================\n");
    fprintf(stderr, "Option: ");
    memset(buff, 0x00, sizeof(buff));
    gets(buff);

    if (buff[0] == 't' || buff[0] == 'T'){          
        ret = tcpserver();          
    } else if (buff[0] == 'c' || buff[0] == 'C'){
        ret = tcpclient();
    } else if (buff[0] == 'o' || buff[0] == 'O'){
        fprintf(stderr, "Enter socket fd:\n");
        gets(buff);         
        ret = close_tcp(atoi(buff));
    } else if (buff[0] == 's' || buff[0] == 'S'){
        fprintf(stderr, "Enter socket fd:\n");
        gets(buff);         
        ret = send_tcp_msg(atoi(buff));
    } 

    }while(buff[0] != 'q' && buff[0] != 'Q');

    return 0;
}

int main(int argc, const char* argv[]){

    nwMenu();

    return 0;
}

Upvotes: 0

Views: 2782

Answers (1)

nos
nos

Reputation: 229058

Your server does:

 saTCPServer.sin_port = 30000;

That should be

 saTCPServer.sin_port = htons(30000);

The port have to be specified in network order, if you're on a little endian machine , 30000 does not translate to the port 30000, but to port 12405. So your server is listening on a different port than what your client is connecting to.

Upvotes: 2

Related Questions