目录
设计思路:
逻辑设计:
代码实现:
运行结果:
设计思路:
- 在服务端客户端T一对一TCP的基础上增加几条通信即可,要求各个连接可同时进行通信因此使用多线程。
- 主线程在listen实现后,使用一个 for 循环一直循环等待客户端的连接请求,将每次连接标记(sockFd)保存作为开启检测(检测条件可自行修改,我这个检测判断貌似也没起啥作用 也先不改了 (▼ヘ▼#),可以采用远端 IP 检查或者 IP+port 等方式来作为检测条件)。
- 每次连接都会开启一个线程用于和客户端的通信(也是使用 for 循环进行数据的接收、处理、发送),数据接收使用阻塞等待。
- 通信的具体实现,在开发板上部署运行下方的服务器端程序,客户端则在PC端网络调试助手开启多个port与服务器完成多个连接进行通信。
逻辑设计:
TCP服务器端逻辑设计
代码实现:
#include <stdio.h>
#include <sys/resource.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <sys/socket.h>
/*********************************************************************************************************
宏定义
*********************************************************************************************************/
#define __TCP_ECHO_TYPE_CLIENT 1 /* 客户端模式 */
#define __TCP_ECHO_TYPE_SERVER 2 /* 服务器模式 */
#define __TCP_ECHO_TYPE (__TCP_ECHO_TYPE_SERVER) /* 当前模式选择 */
#define __TCP_ECHO_IP_CLIENT "192.168.1.16" /* 客户端 IP 地址 */
#define __TCP_ECHO_IP_SERVER "192.168.1.17" /* 服务器 IP 地址 */
#define __TCP_ECHO_PORT_CLIENT 8100 /* 客户端端口号 */
#define __TCP_ECHO_PORT_SERVER 8101 /* 服务器端口号 */
#define __TCP_ECHO_BUFF_SIZE_CLIENT 257 /* 客户端接收缓冲区大小 */
#define __TCP_ECHO_BUFF_SIZE_SERVER 257 /* 服务器接收缓冲区大小 */
/*********************************************************************************************************
** 函数名称: 线程函数
** 功能描述: 为每个tcp连接开启一个线程 用于数据的接收、处理和发送
** 输 入 :
** 输 出 :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
void * tcpThread(void * arg){
int sockFd = *(int *)arg;
char cRecvbuffer[__TCP_ECHO_BUFF_SIZE_SERVER]={0};
ssize_t sstrRecv = 0;
for(;;){
memset(cRecvbuffer, 0, __TCP_ECHO_BUFF_SIZE_SERVER);
sstrRecv = read(sockFd, (void *)cRecvbuffer, __TCP_ECHO_BUFF_SIZE_SERVER);
fprintf(stdout,"TCP server recive: %s\n",cRecvbuffer);
if(sstrRecv <= 0){
if((ETIMEDOUT != 0) && (EWOULDBLOCK != 0)){
close(sockFd);
fprintf(stderr,"TCP server bind error!\n");
return (void *)(-1);
}
continue;
}
write(sockFd, (const void *)cRecvbuffer, sstrRecv);
}
}
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 主函数
** 输 入 : argc,argv
** 输 出 : ERROR
** 全局变量:
** 调用模块:
*********************************************************************************************************/
int main (int argc, char *argv[])
{
int sockFdConn[5]; /* 各客户端的套接口描述符 */
int i, connTemp; /* 临时套接口描述符 */
int connNum; /* 标记当前连接编号 */
int sockFd = -1; /* 套接字描述符 */
int iRet = -1; /* 返回值判断 */
int connMax = -1; /* 连接的客户端总数 */
pthread_t tid[5]; /* 线程句柄 */
struct sockaddr_in sockaddrinRemote;
struct sockaddr_in sockaddrinLocal;
socklen_t size_sin = sizeof(struct sockaddr_in);
sockFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /* 创建本地socket连接 */
if(sockFd < 0){
fprintf(stderr,"tcp server socket creat error!\n");
return -1;
}
fprintf(stdout,"tcp server socket creat success!\n");
/*
* 初始化本地地址结构
*/
memset(sockFdConn, -1, sizeof(sockFdConn));
// memset(sockaddrinLocal, 0 ,sizeof(sockaddrinLocal));
sockaddrinLocal.sin_len = sizeof(struct sockaddr_in);
sockaddrinLocal.sin_family = AF_INET;
sockaddrinLocal.sin_addr.s_addr = INADDR_ANY;
sockaddrinLocal.sin_port = htons(__TCP_ECHO_PORT_SERVER);
/*
* 增加地址复用
*/
iRet = setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &iRet, sizeof(int));
if(iRet < 0){
fprintf(stderr,"TCP reuseADDR error!\n");
return -1;
}
/*
* 绑定本地地址与端口
*/
iRet = bind(sockFd, (struct sockaddr *)&sockaddrinLocal, sizeof(sockaddrinLocal));
if(iRet < 0){
fprintf(stderr,"TCP server bind error!\n");
return -1;
}
fprintf(stdout,"TCP server bind success!\n");
listen(sockFd, 5);
fprintf(stdout,"TCP server bind listening ...\n");
for(;;){
// bzero(&sockaddrinRemote, sizeof(sockaddrinRemote));
connTemp = accept(sockFd, (struct sockaddr *)&sockaddrinRemote, &size_sin);
/* 同客户端创建连接 */
fprintf(stdout,"RemoteAddr:%s, RemotePort:%hu\n", inet_ntoa(sockaddrinRemote.sin_addr),ntohs(sockaddrinRemote.sin_port));
if(connTemp < 0){
close(sockFd);
fprintf(stderr,"TCP server accept error!\n");
return -1;
}
/*
* 检查当前连接是否存在(检查Fd不太合适,可自行修改)
*/
for(i=0; i<=connMax; i++){
if(connTemp == sockFdConn[i]){
connNum =i;
break;
}
}
if(i > connMax){
connNum = ++connMax;
sockFdConn[connNum]=connTemp;
pthread_create(&tid[connNum], NULL, tcpThread, (void*)&sockFdConn[connNum]);
}
// fprintf(stdout,"sockFdConn: %d\n",sockFdConn[cnt]);
}
close(sockFd);
return 0;
}
/*********************************************************************************************************
END
*********************************************************************************************************/
运行结果:
多连接开启
程序进行中