//服务器端
#include "Header.h"
typedef struct
{
char name[10];
SA_IN address;
}USER;
//XXX :用户链表
typedef struct Hnode_list
{
USER data;
struct Hnode_list *next;
}Hlink,*plink;
int memoryError(plink p) ;
int creatUserList(plink head);
int findUser(plink head,char name[10]);
int delUser(plink head,char name[10]);
int getAllUser(plink const head);
int addUser(plink head,USER data);
//XXX :用户链表
void ProcessLogin(char* command,SA_IN rec_addr);
void ProcessChat(char* command);
plink head;
int main(void)
{
char buf[BUFFERSIZE];
SA_IN address, rec_addr;
int socket_fd;
socklen_t length;
head=malloc(sizeof(Hlink));//用户列表头
creatUserList(head); //创建列表
if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) == -1)
{
perror("套接字创建失败");
exit(-1);
}
memset(&address,0,sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(8000);
if(bind(socket_fd,(SA *)&address,sizeof(address)) == -1)
{
perror("套接字绑定失败");
exit(-1);
}
int i=0;
length = sizeof(rec_addr);
while(1)
{
printf("==%d==\n",i);
if(recvfrom(socket_fd,buf,sizeof(buf),0,(SA *)&rec_addr,&length) == -1)
{
perror("接收消息失败");
}
printf("%hu\n",ntohs(rec_addr.sin_port));
switch(buf[0])
{
case 'L':
ProcessLogin(buf,rec_addr);
break;
case 'C':
ProcessChat(buf);
break;
case 'Q':break;
default : printf("ERROR");break;
}
i++;
}
close(socket_fd);
}
void ProcessLogin(char* command,SA_IN rec_addr)
{
int socket_fd;
char name[10];
char ip[32];
char buf[BUFFERSIZE];
USER user;
strcpy(name,command+1);
strcpy(ip,inet_ntoa(rec_addr.sin_addr));
if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) == -1)
{
perror("套接字创建失败");
exit(-1);
}
if(findUser(head,name)==-1)
{
strcpy(user.name,name);
user.address=rec_addr;
addUser(head,user);
buf[0]='Y';
if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&rec_addr,sizeof(rec_addr))==-1)
{
perror("登录失败");
}
}
else
{
buf[0]='N';
if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&rec_addr,sizeof(rec_addr))==-1)
{
perror("登录失败");
}
}
close(socket_fd);
}
void ProcessChat(char* command)
{
int socket_fd;
char buf[BUFFERSIZE];
SA_IN address;
if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) == -1)
{
perror("套接字创建失败");
exit(-1);
}
plink p=head->next;
while(p!=NULL)
{
address=(p->data).address;
sprintf(buf,"%s\n",command+1);
// if(strncmp(buf,(p->data).name,strlen((p->data).name))==0) //屏蔽属于自己的消息
// continue;
if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&address,sizeof(address))<0)
{
perror("消息发送失败");
}
printf("%s:%hu\n",buf,ntohs(address.sin_port));
p=p->next;
}
close(socket_fd);
}
//XXX:使用带头结点的单向链表 存放用户信息
int memoryError(plink p) //判断内存是否申请成功
{
if(p==NULL)
{
printf("MEMORY ERROR!");
return 1;
}
return 0;
}
int creatUserList(plink head)
{
if(memoryError(head))
return -1;
head->next=NULL;
}
int addUser(plink head,USER data) //始终在表头插入
{
plink new_create=malloc(sizeof(Hlink));
if(memoryError(new_create))
return -1;
new_create->data=data;
new_create->next=head->next;
head->next=new_create;
}
int getAllUser(plink const head)
{
plink p=head->next;
while(p!=NULL)
{
printf("%s:%s:%hu\n",(p->data).name,inet_ntoa((p->data).address.sin_addr)
,ntohs((p->data).address.sin_port));
p=p->next;
}
}
int delUser(plink head,char name[10])
{
plink q=head;
plink p=head->next;
while(p!=NULL)
{
if(strcmp((p->data).name,name)==0)
break;
q=p;
p=p->next;
}
if(p==NULL)
{
printf("删除用户失败\n");
return -1;
}
q->next=p->next;
free(p);
p=NULL;
}
int findUser(plink head,char name[10])
{
plink p=head->next;
while(p!=NULL)
{
if(strcmp((p->data).name,name)==0)
return 0;
p=p->next;
}
if(p==NULL)
return -1;
}
//XXX:使用带头结点的单向链表 存放用户信息
//客户端
#include "Header.h"
void dispMessage(int signo);
void killAll(int signo);
char* ProcessLogin(SA_IN serv_addr);
pid_t pid;
int main(void)
{
signal(SIGUSR1,dispMessage);
signal(SIGINT,killAll);
int socket_fd;
char buf[BUFFERSIZE];
char name[10];
SA_IN serv_addr;
//XXX:服务器配置信息
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8000);
//XXX
strcpy(name,ProcessLogin(serv_addr));
if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) == -1)
{
perror("套接字创建失败");
exit(-1);
}
if((pid=fork())==-1)
{
perror("子进程创建失败");
return -1;
}
if(pid==0)//子进程
{
sprintf(buf,"C%s上线了",name); //sendto在此处相当于第一次放送,这跟tcp connect 差不多,会自动分配ip端口号、、错误根源
if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&serv_addr,sizeof(serv_addr)) < 0)
{
perror("发送失败");
}
while(1)
{
pause();
if(recvfrom(socket_fd,buf,sizeof(buf),0,NULL,NULL)==-1)
{
perror("接收消息失败");
}
printf("[收到消息]%s\n",buf);
}
}
char buf_temp[BUFFERSIZE];
while(1)//父进程
{
printf("<请输入>");
scanf("%s", buf_temp);
sprintf(buf,"C%s说:%s",name,buf_temp);
if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&serv_addr,sizeof(serv_addr)) < 0)
{
perror("发送失败");
}
kill(pid,SIGUSR1);
}
}
//Siganl//
void killAll(int signo)
{
printf("\n%d进程结束\n",getpid());
exit(-1);
}
void dispMessage(int signo)
{
;
}
//Siganl//
char* ProcessLogin(SA_IN serv_addr)
{
int socket_fd;
char buf[BUFFERSIZE];
static char name[10];
if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) == -1)
{
perror("套接字创建失败");
exit(-1);
}
while(1)
{
printf("请输入用户名:");
buf[0]='L';
scanf("%s",buf+1);
strcpy(name,buf+1);
if(sendto(socket_fd,buf,sizeof(buf),0,(SA *)&serv_addr,sizeof(serv_addr)) < 0)
{
perror("登录失败");
}
recvfrom(socket_fd,buf,sizeof(buf),0,NULL,NULL);
if(buf[0]=='N')
{
printf("该用户名已被使用,请重新输入用户名\n");
}
else if(buf[0]=='Y')
{
printf("登录成功\n");
close(socket_fd);
return name;
break;
}
}
//printf("==END===\n");
}
//错误原因
yang@ubuntu:~/Day_33/ChartRoom$ ./Server
==0==
43490//登陆端口号
==1==
42934//子进程接受的端口号,不匹配
liu上线了
:43490
==2==
42934
liu说:sdasda
:43490
==3==
42934
liu说:sadasda
:43490
==4==
42934
liu说:adasdas
:4