目录
设计思路:
- 在服务端客户端T一对一TCP的基础上增加几条通信即可,要求各个连接可同时进行通信因此使用多线程。
- 主线程在listen实现后,使用一个 for 循环一直循环等待客户端的连接请求,将每次连接标记(sockFd)保存作为开启检测(检测条件可自行修改,我这个检测判断貌似也没起啥作用 也先不改了 (▼ヘ▼#),可以采用远端 IP 检查或者 IP+port 等方式来作为检测条件)。
- 每次连接都会开启一个线程用于和客户端的通信(也是使用 for 循环进行数据的接收、处理、发送),数据接收使用阻塞等待。
- 通信的具体实现,在开发板上部署运行下方的服务器端程序,客户端则在PC端网络调试助手开启多个port与服务器完成多个连接进行通信。
逻辑设计:
代码实现:
-
#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
-
*********************************************************************************************************/
运行结果:
转载:https://blog.csdn.net/Liangren_/article/details/116765272
查看评论