功能:实现TCP 1个服务端对多个客户端连接功能
服务端编写步骤:
1.创建socket套接字:socket(AF_INET, SOCK_STREAM, 0)
2.初始化本地地址结构:
sockaddrinLocal.sin_family = AF_INET;
sockaddrinLocal.sin_addr.s_addr = inet_addr("127.0.0.1");//IP需改为自己本机IP
sockaddrinLocal.sin_port = htons(6666);
3.绑定地址与端口:bind(sockFd, (struct sockaddr*)&sockaddrinLocal, sizeof(sockaddrinLocal));
4.监听:listen(sockFd, 5);
5.接收客户端连接请求:accept(sockFd, (struct sockaddr*)&sockaddrinRemote, &size_sin);
6.数据接收与发送:
read(sockFd, (void*)cRecvbuffer, __TCP_ECHO_BUFF_SIZE_SERVER);
write(sockFd, (const void*)cRecvbuffer, sstrRecv);
7.结束
测试环境:在Ubuntu上面通过交叉编译工具生成可执行文件,将此文件复制到开发板(RK3568)上面运行,客户端则在PC端网络调试助手开启多个port与服务器完成多个连接进行通信。
Server.c
#include <stdio.h>
#include <stdio.h>
#include <sys/resource.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include<arpa/inet.h>
#define __TCP_ECHO_BUFF_SIZE_SERVER 1024
/*********************************************************************************************************
** 函数名称: 线程函数
** 功能描述: 为每个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 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 ;
sockFd = socket(AF_INET, SOCK_STREAM, 0); /* 创建本地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));
sockaddrinLocal.sin_family = AF_INET;
sockaddrinLocal.sin_addr.s_addr = inet_addr("127.0.0.1");
sockaddrinLocal.sin_port = htons(6666);
/*
* 增加地址复用
*/
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;
}
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;
}
一服务端对多客户端的通信程序参考博客见 TCP服务器连接多客户端(C语言实现)_多客户端连接 tcp服务端 的例子 c-CSDN博客
作者写的非常棒,讲解的也很全面,对它的代码进行了部分修改