0

我正在尝试使用 TCP 服务器/客户端程序,想知道为什么在服务器端,accept() 处的程序循环 ....

我的想法是开发一个 TCP 服务器,它一次接收来自多个客户端的 1 个请求。服务器和客户端之间的连接将在完成单个操作后关闭。例如 1) TCP 服务器应始终监听端口 30000。2)TCP客户端1连接TCP服务器,发送“hello”,等待服务器的“hello”反馈,关闭连接。3)TCP客户端2连接TCP服务器,发送“hello”,等待服务器的“hello”反馈,关闭连接。依此类推,直到 TCP 客户端 n....

上述所有操作都是一次执行的,这意味着 TCP 客户端 1 和 2 不会同时向 TCP 服务器发送消息,并且一旦 TCP 客户端 1 完成操作,它将不再连接到服务器(如果需要,可以触发新连接)。

输出显示

======== 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.

我也期待...

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;
}
4

1 回答 1

2

您的服务器会:

 saTCPServer.sin_port = 30000;

那应该是

 saTCPServer.sin_port = htons(30000);

端口必须按网络顺序指定,如果您使用的是小端机器,则 30000 不会转换为端口 30000,而是转换为端口 12405。因此您的服务器正在侦听的端口与客户端连接的端口不同.

于 2012-05-16T10:07:37.730 回答