服务端
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<pthread.h>
struct SockInfo
{
struct sockaddr_in addr; //地址
pthread_t tid; //进程ID
int fd; //通信套接字
};
struct SockInfo infos[512];
void* working(void* arg);
int main(){
int fd=socket(AF_INET,SOCK_STREAM,0); //创建套接字使用ipv4,流式传输
if(fd == -1)
{
perror("socket");
return -1;
}
struct sockaddr_in saddr;
saddr.sin_family =AF_INET;//使用ipv4
saddr.sin_port=htons(9999);//绑定端口
saddr.sin_addr.s_addr=INADDR_ANY;//绑定地址
int ret =bind(fd,(struct sockaddr*)&saddr,sizeof(saddr));//关联套接字与端口地址
if(ret == -1)
{
perror("bind");
return -1;
}
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
}
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;
}
if(i==max-1)
{
sleep(1);
i--;
}
}
int cfd=accept(fd,(struct sockaddr*)&pinfo->addr,&addrlen);//创建一个新的套接字,用于与
//客户端通信
if(cfd == -1)
{
perror("accept");
break;
}
pinfo->fd=cfd;
pthread_create(&pinfo->tid,NULL,working,pinfo);//创建子线程
pthread_detach(pinfo->tid); //设置分离状态,终止时自动释放所有资源
}
close(fd);
return 0;
}
void* working(void* arg)
{
struct SockInfo* pinfo =(struct SockInfo*)arg;//arg为创建子线程时传入的pinfo
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));
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");
pinfo->fd=-1;
break;
}
else{
perror("recv");
pinfo->fd=-1;
break;
}
}
return NULL;
}
客户端
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
int main(){
int fd=socket(AF_INET,SOCK_STREAM,0);
if(fd == -1)
{
perror("socket");
return -1;
}
struct sockaddr_in saddr;
saddr.sin_family =AF_INET;
saddr.sin_port=htons(9999); //小端字节序转化为大端字节序
inet_pton(AF_INET,"127.0.0.1",&saddr.sin_addr.s_addr);//本地测试使用127.0.0.1
int ret =connect(fd,(struct sockaddr*)&saddr,sizeof(saddr));
if(ret == -1)
{
perror("connect");
return -1;
}
int number=0;
while(1){
char buff[1024];
sprintf(buff,"hello world...%d\n",number++);
send(fd,buff,strlen(buff)+1,0);
memset(buff,0,sizeof(buff)); //初始化,清空buff
int len=recv(fd,buff,sizeof(buff),0);
if(len>0)
{
printf("server say: %s\n",buff);
}
else if(len==0)
{
printf("服务端断开了连接\n");
}
else{
perror("recv");
break;
}
sleep(1);
}
close(fd);
return 0;
}
代码运行平台,编译器:ubuntu22.04+gcc
gcc server.c -lpthread -o server
gcc client.c -o client
./server
添加一个或多个新终端 ./client