
server.c
#include <iohead.h>
#define MAX_CLIENTS 100
/*typedef struct
{
int sockid;//客户端的套接字
int id;//服务器给客户端分配id;
}Client;
Client clients[MAX_CLIENTS];//客户端数组
int next_id = 1;
//为客户端分配id
int add_clientid(int sockfd)
{
if(next_id>MAX_CLIENTS)
{
printf("分配失败\n");
return -1;
}
clients[next_id].sockid = sockfd;
clients[next_id].id = next_id;
return next_id++;
}*/
//讲一个拥有(描述符,监视方式,激活形式)的结构体变量fd,存放在监视列表arr中,并且监视列表的长度len自增1
void insert_fd(struct pollfd* arr,struct pollfd newfd,int* len)
{
arr[*len] = newfd;
(*len)++;
}
//将想要删除的描述符fd,从监视列表Arr中删除,并且监视列表长度len自减1
void remove_fd(struct pollfd* arr,int fd,int* len)
{
int i;
for(i=0;i<*len;i++)
{
if(arr[i].fd == fd)
{
int j=0;
for(j=i;j<*len-1;j++)
{
arr[j]=arr[j+1];
}
//arr[j]=-1;//将删除空出来的一个位置,变成非法描述符,不变也可以
}
}
(*len)--;
}
int main(int argc, const char *argv[])
{
if(argc<2){
printf("请输入端口号\n");
return 1;
}
short port = atoi(argv[1]); // argv[1] = "8888" -> 00111000 00111000 00111000 00111000
//int a = 8888 -> 00000000 00000000 00100010 10111000
//printf("port = %d\n",port);
int client_arr[10] = {0};//用来存放所有客户端套接字的数组
int client_count = 0;//记录客户端套接字的数量
int server = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr("0.0.0.0");
if(bind(server,(struct sockaddr*)&addr,sizeof(addr)) == -1){
perror("bind");
return 1;
}
listen(server,10);
//准备一个poll监视列表(同时也是激活列表)
struct pollfd list[10]={0};
int list_len = 0;//用来记录监视列表中描述符的数量
//先准备想要监视的描述符,注意将描述符联通监视形式,存入结构体中,应为监视列表是这个结构体形式的数组
struct pollfd poll_server = {fd:server,events:POLLIN,revents:0};
struct pollfd poll_stdin = {fd:0,events:POLLIN,revents:0};
//将想要监视的描述符,存放监视列表list中:server,0
insert_fd(list,poll_server,&list_len);
insert_fd(list,poll_stdin,&list_len);
while(1)
{
poll(list,list_len,-1);
for(int i=0;i<list_len;i++)
{
int fd = list[i].fd;
if(list[i].revents == POLLIN)
{
//说明list[i].fd被激活了
if(fd==server)
{
//如果激活的是服务器
printf("有新客户端链接\n");
int client = accept(server,NULL,NULL);
//记得将新链接的客户端加入监视列表中
struct pollfd poll_client={fd:client,events:POLLIN,revents:0};
insert_fd(list,poll_client,&list_len);
//add_clientid(client);
continue;
}
if(fd == 0)
{
//如果激活的是标准输入流
char buf[1024]="";
scanf("%1023s",buf);
getchar();
printf("键盘输入的数据:%s\n",buf);
continue;
}
char buf[64]="";
int res=read(fd,buf,64);
if(res==0)
{
printf("客户端断开\n");
remove_fd(list,fd,&list_len);
close(fd);
}
else
{
for(int j=0;j<list_len;j++)
{
if(list[j].fd==server){continue;}
if(list[j].fd==0){continue;}
if(list[j].fd!=list[i].fd)
{
int res1=send(list[j].fd,buf,strlen(buf)+1,0);
if(res1<=0)
{
printf("客户端之间连接失败\n");
break;
}
}
}
}
}
}
}
return 0;
}
client1.c
#include <iohead.h>
int main(int argc, const char *argv[])
{
if(argc<2)
{
printf("请输入端口号\n");
return 1;
}
int port = atoi(argv[1]);
int client = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr("192.168.220.128");
if(connect(client,(struct sockaddr*)&addr,sizeof(addr))==-1)
{
perror("bind");
return 1;
}
//准备一个select监视列表;
fd_set list;
//初始化
FD_ZERO(&list);
//将想要监视的描述符,添加进入监视列表list中:server,0
FD_SET(client,&list);
FD_SET(0,&list);
int max=4;
while(1)
{
fd_set temp = list;
select(max,&temp,NULL,NULL,NULL);
//判断摸个描述符是否在监视列表里面
if(FD_ISSET(client,&temp))
{
// printf("将client传送给服务器\n");
char buf[64]={0};
int res = recv(client,buf,sizeof(buf),0);
if(res<=0)
{
printf("客户端断开\n");
break;
}
printf("收到消息%s\n",buf);
}
if(FD_ISSET(0,&temp))
{
printf("将消息发送给服务器\n");
char buf[64]={0};
//printf("请输入:");
scanf("%s",buf);
getchar();
fflush(stdout);
int res1 = send(client,buf,strlen(buf)+1,0);
if(res1<=0)
{
printf("服务器断开\n");
break;
}
// printf("发送消息%s\n",buf);
}
}
close(client);
return 0;
}
client2
#include <iohead.h>
/*typedef struct
{
int client_id;
volatile int *running;
}threadarg;*/
void* thread_main(void* arg)
{
int client=*(int*)arg;
while(1)
{
char buf[64]={0};
int res1 = recv(client,buf,sizeof(buf),0);
if(res1<=0)
{
printf("连接失败\n");
break;
}
printf("服务端发来消息%s\n",buf);
}
return NULL;
}
int main(int argc, const char *argv[])
{
if(argc<2)
{
printf("请输入端口号\n");
return 1;
}
int port = atoi(argv[1]);
int client = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr("192.168.220.128");
if(connect(client,(struct sockaddr*)&addr,sizeof(addr))==-1)
{
perror("bind");
return 1;
}
/*volatile int running=1;
threadarg *arg=malloc(sizeof(threadarg));
arg->client_id=client;
arg->running=&running;*/
//创建子进程
pthread_t id=0;
pthread_create(&id,NULL,thread_main,&client);
pthread_detach(id);
while(1)
{
//printf("请输入:");
char buf[64]={0};
scanf("%s",buf);
getchar();
fflush(stdout);
int res = send(client,buf,strlen(buf)+1,0);
if(res<=0)
{
//running = 0;
break;
}
printf("已经发送%s\n",buf);
}
close(client);
return 0;
}
341

被折叠的 条评论
为什么被折叠?



