1.项目:建立服务器和客户端(客户端发出的信息其他客户端接收,服务器发出的信息全部客户端接收)
服务器代码:
cs
#include <25061head.h>
#define SER_IP "192.168.109.126"
#define SER_PORT 8888
typedef struct Node
{
union
{
int data;
int len;
};
char username[50];
struct sockaddr_in addr;
struct Node *next;
}*linklist;
linklist creat_head()
{
linklist head=(linklist)malloc(sizeof(struct Node));
if(head==NULL)
{
return NULL;
}
head->len=0;
head->next=NULL;
return head;
}
linklist creat_node(int fd,const char* name,struct sockaddr_in addr)
{
linklist s=(linklist)malloc(sizeof(struct Node));
if(NULL==s)
{
return NULL;
}
s->data=fd;
strncpy(s->username,name,sizeof(s->username)-1);
s->username[sizeof(s->username)-1]='\0';
s->next=NULL;
return s;
}
int insert_rear(int fd,const char* name,struct sockaddr_in addr,linklist head)
{
if(NULL==head)
{
return -1;
}
linklist s=creat_node(fd,name,addr);
if(NULL==s)
{
return -1;
}
linklist p=head;
while(p->next!=NULL)
{
p=p->next;
}
p->next=s;
head->len++;
return 0;
}
int delete_client(linklist head,int fd)
{
if(NULL==head||NULL==head->next)
{
return -1;
}
linklist prev=head;
linklist curr=head->next;
while(curr!=NULL)
{
if(curr->data==fd)
{
prev->next=curr->next;
free(curr);
head->len--;
return 0;
}
prev=curr;
curr=curr->next;
}
return -1;
}
const char *find_username(linklist head,int fd)
{
linklist p=head->next;
while(p!=NULL)
{
if(p->data==fd)
{
return p->username;
}
p=p->next;
}
return "unknown";
}
void broadcast(linklist head,char *msg,int exclude_fd)
{
linklist p=head->next;
while(p!=NULL)
{
if(p->data!=exclude_fd)
{
send(p->data,msg,strlen(msg),0);
}
p=p->next;
}
}
int main(int argc, const char *argv[])
{
linklist head=creat_head();
if(head==NULL)
{
perror("creat_head error");
return -1;
}
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(-1==sfd)
{
perror("socket error");
return -1;
}
printf("socket success sfd=%d\n",sfd);
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1)
{
perror("setsockopt error");
return -1;
}
printf("端口号快速重用成功\n");
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(SER_PORT);
sin.sin_addr.s_addr=inet_addr(SER_IP);
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("bind error");
return -1;
}
printf("bind success\n");
if(listen(sfd,128)==-1)
{
perror("listen error");
return -1;
}
printf("listen success\n");
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
char buf[256]="";
fd_set readsfds;
FD_ZERO(&readsfds);
FD_SET(0,&readsfds);
FD_SET(sfd,&readsfds);
fd_set tempfds;
int maxfd=sfd;
while(1)
{
tempfds=readsfds;
int res=select(maxfd+1,&tempfds,NULL,NULL,NULL);
if(res==-1)
{
perror("select error");
break;
}
else if(res==0)
{
printf("time out\n");
continue;
}
if(FD_ISSET(sfd,&tempfds))
{
int new_fd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(-1==new_fd)
{
perror("accept error");
continue;
}
char username_buf[50]={0};
ssize_t name_len=recv(new_fd,username_buf,sizeof(username_buf),0);
if(name_len<=0)
{
perror("recv name error");
close(new_fd);
continue;
}
username_buf[name_len]='\0';
if(insert_rear(new_fd,username_buf,cin,head)==0)
{
printf("新客户端:%s(fd=%d)\n",username_buf,new_fd);
char join_msg[256];
snprintf(join_msg,sizeof(join_msg),"[系统]%s登录",username_buf);
broadcast(head,join_msg,-1);
}
FD_SET(new_fd,&readsfds);
if(new_fd>maxfd)
{
maxfd=new_fd;
}
printf("[%s:%d] fd=%d username=%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),new_fd,username_buf);
}
//服务器向客户端发送信息
if(FD_ISSET(0,&tempfds))
{
if(fgets(buf,sizeof(buf),stdin)==NULL)
{
perror("fgets error");
continue;
}
if(strlen(buf)==0)
{
continue;
}
char system_msg[2048];
snprintf(system_msg,sizeof(system_msg),"[系统公告]:%s",buf);
broadcast(head,system_msg,-1);
}
for(int i=sfd+1;i<=maxfd;i++)
{
if(FD_ISSET(i,&tempfds))
{
char rbuf[128]="";
ssize_t res=recv(i,rbuf,sizeof(rbuf)-1,0);
if(res==0)
{
const char *username=find_username(head,i);
printf("客户端%s(fd=%d)已下线\n",username,i);
char leave[256];
snprintf(leave,sizeof(leave),"[系统]:%s下线",username);
broadcast(head,leave,i);
close(i);
FD_CLR(i,&readsfds);
delete_client(head,i);
if(i=maxfd)
{
for(int j=maxfd-1;j>=sfd;j--)
{
if(FD_ISSET(j,&readsfds))
{
maxfd=j;
break;
}
}
}
continue;
}
if(res==-1)
{
perror("recv error");
close(i);
FD_CLR(i,&readsfds);
delete_client(head,i);
continue;
}
rbuf[res]='\0';
const char *sender_name=find_username(head,i);
char fullmsg[512];
snprintf(fullmsg,sizeof(fullmsg),"[%s]:%s",sender_name,rbuf);
broadcast(head,fullmsg,i);
}
}
}
close(sfd);
linklist curr=head->next;
while(curr!=NULL)
{
linklist next=curr->next;
close(curr->data);
free(curr);
curr=next;
}
free(head);
return 0;
}
客户端代码:
cs
#include <25061head.h>
#define SER_PORT 8888
#define SER_IP "192.168.109.126"
int cfd;
void *callback(void* arg)
{
char buf[256];
while(1)
{
ssize_t res=recv(cfd,buf,sizeof(buf)-1,0);
if(res<=0)
{
printf("与服务器断开连接\n");
close(cfd);
exit(0);
}
buf[res]='\0';
printf("%s\n",buf);
fflush(stdout);
}
return NULL;
}
int main(int argc, const char *argv[])
{
if(argc!=4)
{
printf("%s[用户名][服务器IP][端口号]\n",argv[0]);
return -1;
}
const char *username=argv[1];
const char *system_ip=argv[2];
int port=atoi(argv[3]);
cfd=socket(AF_INET,SOCK_STREAM,0);
if(-1==cfd)
{
perror("socket error");
return -1;
}
printf("socket success cfd=%d\n",cfd);
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(port);
sin.sin_addr.s_addr=inet_addr(system_ip);
if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("connect error");
return -1;
}
printf("连接成功\n");
send(cfd,username,strlen(username),0);
pthread_t thread=-1;
if(pthread_create(&thread,NULL,callback,NULL)!=0)
{
printf("线程创建失败\n");
close(cfd);
return -1;
}
pthread_detach(thread);
char buf[256];
while(1)
{
if(fgets(buf,sizeof(buf),stdin)==NULL)
{
break;
}
if(strcmp(buf,"quit")==0)
{
break;
}
send(cfd,buf,strlen(buf),0);
}
close(cfd);
return 0;
}
结果:

