#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>//包含soocket.h
#include<pthread.h>
#define MAX_NUM 10
//信息结构体
struct SockInfo
{
struct sockaddr_in addr;
int fd;
};
struct SockInfo infos[MAX_NUM];
void *working(void *arg);
int main()
{
//1.创建监听的套接字
int fd=socket(AF_INET,SOCK_STREAM,0);//AF_INET是ipv4,sock_stream是流式协议
if(fd == -1)
{
perror("socket");
return -1;
}
//2.绑定本地的IP port
struct sockaddr_in saddr;
saddr.sin_family=AF_INET;
saddr.sin_port=htons(9999);//转换为大端,主机字节序转换为网络字节序
saddr.sin_addr.s_addr=INADDR_ANY;//读取本地网卡的ip地址
int ret=bind(fd,(struct sockaddr*)&saddr,sizeof(saddr));
if(ret==-1)
{
perror("bind");
return -1;
}
//3.设置监听
ret=listen(fd,128);
if(ret == -1)
{
perror("listen");
return -1;
}
//初始化结构体数组
int max=sizeof(infos)/sizeof(infos[0]);
for(int i=0;i<max;i++)
{
bzero(&infos[i],sizeof(infos[i]));
infos[i].fd=-1;//套接字状态默认为-1,用来判断哪个fd是空闲的
}
//4.阻塞并等待客户端的连接
int addrlen=sizeof(struct sockaddr_in);
while(1)
{
struct SockInfo* pinfo;
for(int i=0;i<max;i++)
{
if(infos[i].fd==-1)
{
pinfo=&infos[i];
break;
}
}
int cfd=accept(fd,(struct sockaddr*)&pinfo->addr,&addrlen);
pinfo->fd=cfd;
if(cfd == -1)
{
perror("accept");
return -1;
}
//创建子线程
pthread_t tid;
pthread_create(&tid,NULL,working,pinfo);
pthread_detach(tid);
}
close(fd);
return 0;
}
void *working(void *arg)
{
struct SockInfo* pinfo=(struct SockInfo*)arg;
//连接建立成功,打印客户端的IP地址及端口信息
char ip[32];
printf("客户端的IP:%s,端口:%d\n",
inet_ntop(AF_INET,&pinfo->addr.sin_addr.s_addr,ip,sizeof(ip))
,ntohs(pinfo->addr.sin_port));//inet_ntop 大端转小端;ntohs 网络字节序转主机字节序
//5.通信
while(1)
{
//接受数据
char buff[1024];
int len=recv(pinfo->fd,buff,sizeof(buff),0);
if(len > 0)
{
printf("client say: %s\n",buff);
send(pinfo->fd,buff,len,0);
}
else if(len == 0)
{
printf("客户端已经断开连接。。。\n");
break;
}
else
{
perror("recv");
break;
}
}
//关闭文件描述符
close(pinfo->fd);
pinfo->fd=-1;
return NULL;
}