硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3731|回复: 5
收起左侧

[RL-TCPnet] 请教如何实现 TCP服务器的多连接

[复制链接]

2

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2017-9-28 19:41:49 | 显示全部楼层 |阅读模式
比方说建立了一个 TCP服务器,端口为 5000,现在只能是一个客户端可以成功连接,第2个就连不上。假如我需要多个客户端可以同时连接 5000这个端口,应该怎么做啊?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
发表于 2017-9-29 01:00:14 | 显示全部楼层
简单点,创建多个tcp服务器,监听同一个端口即可,因为TCP通信是一对一,一个服务器对应一个客户端。

或者使用BSD Socket,可以设置监听多个连接,会自动创建TCP服务器处理客户端来的连接。
回复

使用道具 举报

25

主题

99

回帖

179

积分

初级会员

积分
179
发表于 2017-9-29 09:02:01 | 显示全部楼层

回 eric2013 的帖子

eric2013:
简单点,创建多个tcp服务器,监听同一个端口即可,因为TCP通信是一对一,一个服务器对应一个客户端。

或者使用BSD Socket,可以设置监听多个连接,会自动创建TCP服务器处理客户端来的连接。
BSD有没有

select()这个函数,lwip里用bsd的时候有这个,看您的教程里直接是监听,等待连接,接收数据,没有判断是哪个的数据啊?还是内部已经处理过了?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
发表于 2017-9-29 09:17:39 | 显示全部楼层

回 xujun 的帖子

xujun:BSD有没有

select()这个函数,lwip里用bsd的时候有这个,看您的教程里直接是监听,等待连接,接收数据,没有判断是哪个的数据啊?还是内部已经处理过了?

....... (2017-09-29 09:02) 
无此函数,可以accept的时候获取是来自哪个IP。
回复

使用道具 举报

2

主题

2

回帖

2

积分

新手上路

积分
2
 楼主| 发表于 2017-9-29 19:38:51 | 显示全部楼层
多谢版主,去试一下
回复

使用道具 举报

5

主题

20

回帖

35

积分

新手上路

积分
35
发表于 2021-3-11 15:47:16 | 显示全部楼层
同样碰到这个问题,在官方找到了另外一个方法,放过来供大家参考
https://www.keil.com/support/man ... _tn_tcp_mulconn.htm

The framework of the user application shall contain the following basic functions:

The user_init() function to initialize all user application sessions at startup.
void user_init () {
  USER_INFO *user_s;
  int i;

  for (i = 0; i < user_num_sess; i++) {
    user_s = &user_session;
    user_s->Count = 0;
    user_s->Flags = 0;
    user_s->BCnt  = 0;
    user_s->Tout  = 0;
    user_s->File  = NULL;
    user_s->Script= NULL;
    /* Allocate a TCP socket for the session. */
    user_s->Socket = tcp_get_socket (TCP_TYPE_SERVER, TCP_TOS_NORMAL,
                     120, user_listener);
    user_s->State = USER_STATE_ERROR;
    if (user_s->Socket != 0) {
      if (tcp_listen (user_s->Socket, USER_SERVER_PORT) == __TRUE) {
        user_s->State = USER_STATE_IDLE;
      }
    }
  }
}
All user sessions are now initialized and each session has allocated it's own TCP socket. A socket is listening on selected USER_SERVER_PORT port.
The user_listener() callback function for TCP socket. This callback function is common for all TCP sockets allocated in this user application.
static U16 user_listener (U8 socket, U8 event, U8 *ptr, U16 par) {
  USER_INFO *user_s;
  U8 session;
  int i;

  session = user_map_session (socket);
  if (session == 0)) {
    return (__FALSE);
  }
  user_s = &user_session[session-1];
  switch (event) {
    case TCP_EVT_CONREQ:
      if (user_s->State == USER_STATE_IDLE) {
        user_s->State = USER_STATE_RESERVED;
      }
      return (__TRUE);

    case TCP_EVT_ABORT:
      user_kill_session (user_s);
      return (__TRUE);

    case TCP_EVT_CONNECT:
      user_s->State = USER_STATE_ACTIVE;
      return (__TRUE);

    case TCP_EVT_CLOSE:
      user_kill_session (user_s);
      return (__TRUE);

    case TCP_EVT_ACK:
      user_s->Count += user_s->BCnt;
      user_s->BCnt = 0;
      return (__TRUE);

    case TCP_EVT_DATA:
       ..
      return (__TRUE);
  }
  return (__FALSE);
}
The user_map_session() function to map the socket, which has generated a callback event, to it's owner session.
static U8 user_map_session (U8 socket) {
  int i;

  for (i = 1; i <= user_num_sess; i++) {
    if (user_session[i-1].Socket == socket) {
      return (i);
    }
  }
  return (0);
}
The user_kill_session() function to initialize the session to a default state, close any eventually opened files and release any eventually allocated buffers.
static void user_kill_session (USER_INFO *user_s) {

  user_s->State =  USER_STATE_IDLE;
  if (user_s->Flags & USER_FLAG_FOPENED) {
    user_fclose (user_s->File);
    user_s->File = NULL;
  }
  if (user_s->Script != NULL) {
    free_mem (user_s->Script);
    user_s->Script = NULL;
  }
  user_s->Flags = 0;
  user_s->Count = 0;
  user_s->BCnt  = 0;
  user_s->Tout  = 0;
}
The user_run_server() function to maintain the application jobs, timeouts, etc. This function shall be frequently called from the main loop.
void user_run_server () {
  USER_INFO *user_s;
  int i;

  for (i = 0; i < user_num_sess; i++) {
    user_s = &user_session;

    switch (user_s->State) {
      case USER_STATE_IDLE:
      case USER_STATE_RESERVED:
        /* Keep TCP sockets listening. */
        if (tcp_get_state (user_s->Socket) < TCP_STATE_LISTEN) {
          tcp_listen (user_s->Socket, USER_SERVER_PORT);
        }
        break;
      case USER_STATE_WAITING:
        if (sec_tick == __TRUE) {
          if (--user_s->Tout == 0) {
            /* A timeout expired. */
            user_kill_session (user_s);
          }
        }
        break;
      case USER_STATE_ACTIVE:
         ..
        break;
    }
  }
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-28 23:35 , Processed in 0.174949 second(s), 31 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表