Linux TCP server 只能接受一个 TCP 连接

时间:2023-03-09 07:56:33
Linux  TCP server  只能接受一个 TCP 连接
#include <stdio.h>

#include <sys/types.h>
#include <sys/socket.h> #include <string.h> // menset 函数
#include <stdlib.h> // exit 函数 #include<netinet/in.h> // struct sockaddr_in 结构类型 #include<arpa/inet.h> // inet_ntoa 函数 #include <unistd.h> // close 函数 int tcpServerInit( void ); void main()
{
//2017年11月28日11:18:18,suozhang,add
printf("2017年11月28日11:18:39,hello,world!\r\n"); tcpServerInit(); } int tcpServerInit( void )
{
// AF_INET : IPV4网络协议
// SOCK_STREAM : 提供双向连续且可信赖的数据流,即TCP,支持OOB机制,在所有数据传输前必须使用connect()来建立连接状态
// 0 : 用来指定socket所使用的传输协议编号,通常此参考不用管他,设为0即可
int tcpServerSocket = socket(AF_INET, SOCK_STREAM, ); if(tcpServerSocket < )
{
// 创建 socket 失败
// perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。
perror("new tcpServerSocket error is "); //exit(-1)表示程序异常退出
exit(-);
} //定义 服务器 IP地址和端口号 结构体变量
struct sockaddr_in tcpServerAddr; //将结构体清空
memset(&tcpServerAddr,,sizeof(tcpServerAddr)); tcpServerAddr.sin_family = AF_INET; // AF_INET : IPV4网络协议 // htons() 函数用来将 16位 类型 转换为 网络字符顺序
tcpServerAddr.sin_port = htons();// 绑定端口号为9527,通常是大于1024的一个值 // inet_addr() 函数用来将IP地址字符串转换成网络所使用的二进制数字
tcpServerAddr.sin_addr.s_addr = inet_addr("10.1.51.53");// 这里可填写 INADDRY_ANY 表示服务器自动填充本机IP地址 if( bind(tcpServerSocket, (struct sockaddr*)&tcpServerAddr, sizeof(tcpServerAddr)) < )
{
//绑定失败
perror("bind tcpServerSocket err is "); close( tcpServerSocket ); //绑定失败,因此关闭创建的 socket //exit(-1)表示程序异常退出
exit(-);
} printf("TCP server ip: %s and port: %d.\r\n", inet_ntoa(tcpServerAddr.sin_addr), ntohs(tcpServerAddr.sin_port)); //监听socket ,第二个参数规定了内核应该为相应套接口排队的最大连接个数。
if( listen(tcpServerSocket, ) < )
{
//监听失败
perror("listen tcpServerSocket err is "); close( tcpServerSocket ); //绑定失败,因此关闭创建的 socket //exit(-1)表示程序异常退出
exit(-);
} struct sockaddr_in tcpClientAddr; //将结构体清空
memset(&tcpClientAddr,,sizeof(tcpClientAddr)); socklen_t tcpClientAddrLen = sizeof(struct sockaddr); // accept() 函数 接受远程计算机的连接请求,建立与客户机之间的通信连接。
// 服务器处于监听状态时,如果某时刻获得客户机的连接请求,此时并不是立即处理这个请求,
// 而是将这个请求放在等待队列中,当系统空闲时再处理客户机的连接请求。
// 重点: 当 accept() 函数接受一个连接时,会返回一个新的socket标识符,
// 以后的数据传输和读取就要通过这个新的socket编号来处理,
// 原来参数的socket(这里指 tcpServerSocket )也可以继续使用,继续监听其他客户机的连接请求
// 因此 服务器跟一个客户端连接成功,就会产生两个套接字,一个当初自己创建的,一个 accept() 创建的 int tcpClientSocket = accept(tcpServerSocket, (struct sockaddr*)&tcpClientAddr, &tcpClientAddrLen); if( tcpClientSocket < )
{
perror("accept tcpServerSocket err is "); close( tcpServerSocket ); //绑定失败,因此关闭创建的 socket //exit(-1)表示程序异常退出
exit(-);
}
else
{
printf("connected with ip: %s and port: %d.\r\n", inet_ntoa(tcpClientAddr.sin_addr), ntohs(tcpClientAddr.sin_port));
} char buf[] ={ }; for( ;; )
{
if( recv( tcpClientSocket, buf, sizeof( buf ), ) < )
{
perror("recv tcpClientSocket err is "); close( tcpServerSocket ); //绑定失败,因此关闭创建的 socket close( tcpClientSocket ); //绑定失败,因此关闭创建的 socket //exit(-1)表示程序异常退出
exit(-);
} printf("接收的数据是:%s.\r\n",buf); //将接收的数据发回客户端
if( send( tcpClientSocket,buf,strlen(buf), ) < )
{
perror("send tcpClientSocket err is "); close( tcpServerSocket ); //绑定失败,因此关闭创建的 socket close( tcpClientSocket ); //绑定失败,因此关闭创建的 socket //exit(-1)表示程序异常退出
exit(-);
} //将接收缓冲区清空
memset(buf,,sizeof(buf)); } }