1.服务器
#include <head.h>
typedef struct Node{
union{
int len;
struct sockaddr_in sin;
};
struct Node* next;
}*node;
typedef struct tell{
char type; //L:登录 C:聊天 Q:退出
char name[20];
char text[128];
}talk;
typedef struct inform{
char name[20];
char text[128];
}usr_inf;
typedef struct information{
struct sockaddr_in cin;
struct inform usr_inf;
}inf;
#define ERR_MSG(msg) do{\
fprintf(stderr,"line: %d\n",__LINE__);\
perror(msg);\
return -1;\
}while(0);
//#define IP "192.168.74.189"
//#define IP "192.168.8.220"
#define IP "192.168.0.226"
#define PORT 8888
void* getout(void* arg);
void* join(void* arg);
void* traver(void* arg);
void* error(void* arg);
void* forword(void* arg);
node link1;
int sfd;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int main(int argc,const char * argv[])
{
sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0){
ERR_MSG("socket");
return -1;
}
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
if((bind(sfd,(struct sockaddr*)&sin,sizeof(sin))) < 0){
ERR_MSG("bind");
return -1;
}
printf("绑定成功\n");
pthread_t tid,tid1;
struct sockaddr_in cin;
socklen_t len = sizeof(cin);
char buf[128] = "";
talk infor;
int res = 0;
link1 = (struct Node*)malloc(sizeof(struct Node));
link1->next = NULL;
link1->len = 0;
inf node;
memset(&infor,0,sizeof(infor));
if((pthread_create(&tid1,NULL,(void*)forword,NULL)) < 0){
printf("error __%d__\n",__LINE__);
return -1;
}
while(1){
res = recvfrom(sfd,&infor,sizeof(infor),0,(struct sockaddr*)&cin,&len);
if(res < 0){
ERR_MSG("recvfrom");
return -1;
}
if('L' == infor.type||'l' == infor.type){
inf urse;
memset(&urse.cin,0,sizeof(struct Node));
strcpy(urse.usr_inf.name,infor.name);
strcpy(urse.usr_inf.text,"上线了!!!");
urse.cin = cin;
if((pthread_create(&tid,NULL,(void*)join,(void*)&urse)) < 0){
printf("error __%d__\n",__LINE__);
return -1;
}
pthread_detach(tid);
}else if('C' == infor.type||'c' == infor.type){
inf urse;
strcpy(urse.usr_inf.name,infor.name);
strcpy(urse.usr_inf.text,infor.text);
urse.cin = cin;
if((pthread_create(&tid,NULL,(void*)traver,(void*)&urse)) < 0){
printf("error __%d__\n",__LINE__);
return -1;
}
pthread_detach(tid);
}else if('Q' == infor.type||'q' == infor.type){
inf urse;
strcpy(urse.usr_inf.name,infor.name);
strcpy(urse.usr_inf.text,"下线了!!!");
urse.cin = cin;
if((pthread_create(&tid,NULL,(void*)getout,(void*)&urse)) < 0){
printf("error __%d__\n",__LINE__);
return -1;
}
pthread_detach(tid);
}else{
inf urse;
strcpy(urse.usr_inf.name,"**Server**");
strcpy(urse.usr_inf.text,"WRONG TYPE");
urse.cin = cin;
if((pthread_create(&tid,NULL,(void*)error,(void*)&urse)) < 0){
printf("error __%d__\n",__LINE__);
return -1;
}
}
}
pthread_mutex_destroy(&mutex);
return 0;
}
void *traver(void* arg){
pthread_mutex_lock(&mutex);
struct information urse_1;
urse_1 = *(struct information*)arg;
node p = link1;
if(0 == link1->len)
{
strcpy(urse_1.usr_inf.name,"**Server**");
strcpy(urse_1.usr_inf.text,"请先登录");
if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
printf("error __%d__",__LINE__);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
}
for(int i = 0; i < link1->len; i++){
p = p->next;
if(0 == memcmp(&p->sin,&urse_1.cin,sizeof(p->sin))){
break;
}
if(NULL == p->next){
strcpy(urse_1.usr_inf.name,"**Server**");
strcpy(urse_1.usr_inf.text,"请先登录");
if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
printf("error __%d__",__LINE__);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
}
p = link1;
for(int i = 0; i < link1->len; i++){
p = p->next;
if(0 != memcmp(&p->sin,&urse_1.cin,sizeof(p->sin))){
if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&p->sin,sizeof(p->sin))) < 0){
printf("error __%d__",__LINE__);
break;
}
}
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void* join(void* arg){
pthread_mutex_lock(&mutex);
struct information urse_1;
urse_1 = *(struct information*)arg;
node ptr;
ptr = (node)malloc(sizeof(struct Node));
memset(ptr,0,sizeof(struct Node));
ptr->sin = urse_1.cin;
node p;
p = link1;
printf(" __%d__\n",__LINE__);
for(int i = 0; i < link1->len; i++){
p = p->next;
if(!memcmp(&p->sin,&urse_1.cin,sizeof(p->sin))){
strcpy(urse_1.usr_inf.text,"请不要重复登录");
if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
printf("error __%d__",__LINE__);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
}
p = link1;
for(int i = 0; i < link1->len; i++){
p = p->next;
if(0 != memcmp(&p->sin,&urse_1.cin,sizeof(p->sin))){
if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&p->sin,sizeof(p->sin))) < 0){
printf("error __%d__",__LINE__);
break;
}
}
}
strcpy(urse_1.usr_inf.text,"登陆成功");
strcpy(urse_1.usr_inf.name,"**Server**");
if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
printf("error __%d__",__LINE__);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
ptr->next = p->next;
p->next = ptr;
link1->len++;
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void* getout(void* arg){//登出
pthread_mutex_lock(&mutex);
struct information urse_1;
urse_1 = *(struct information*)arg;
node p = link1;
node q ;
for(int i = 0; i < link1->len; i++){
p = p->next;
if(0 == memcmp(&p->sin,&urse_1.cin,sizeof(p->sin))){//如果他在链表中我就执行给其他人发信息不在链表中我需要他先登录
break;
}
if(NULL == p->next){
strcpy(urse_1.usr_inf.name,"**Server**");
strcpy(urse_1.usr_inf.text,"请先登录");
if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
printf("error __%d__",__LINE__);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
}
p = link1;
for(int i = 0; i < link1->len; i++){
if(0 == memcmp(&p->next->sin,&urse_1.cin,sizeof(p->sin))){
q = p ->next;
p->next = q->next;
free(q);
q = NULL;
link1->len--;
break;
}
p = p->next;
}
p = link1;
for(int i = 0; i < link1->len; i++){
p = p->next;
if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&p->sin,sizeof(p->sin))) < 0){
printf("error __%d__",__LINE__);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void* error(void* arg){
struct information urse_1;
urse_1 = *(struct information*)arg;
if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
printf("error __%d__",__LINE__);
}
pthread_exit(NULL);
return NULL;
}
void* forword(void* arg){
usr_inf usr1;
strcpy(usr1.name,"**Server**");
char buf[128] = "";
int i = 0;
node p = link1;
int res = 0;
while(1){
printf("请输入全体信息>>>>");
scanf("%s",buf);
strcpy(usr1.text,buf);
for(i = 0;i < link1->len;i++){
p = p->next;
res = sendto(sfd,&usr1,sizeof(usr1),0,(struct sockaddr*)&p->sin,sizeof(p->sin));
if(res < 0){
printf("error __%d__",__LINE__);
pthread_exit(NULL);
}
}
}
pthread_exit(NULL);
}
2.客户端
#include <head.h>
//传递给线程的结构体
struct cli_msg
{
int newfd;
struct sockaddr_in cin;
};
typedef struct node{
char type; //L:登录 C:聊天 Q:退出
char name[20];
char text[128];
}talk;
typedef struct inform{
char name[20];
char text[128];
}usr_inf;
#define ERR_MSG(msg) do{\
fprintf(stderr,"line: %d\n",__LINE__);\
perror(msg);\
return -1;\
}while(0);
//ip地址和端口
//#define IP "192.168.74.189"
//#define IP "192.168.8.220"
#define IP "192.168.0.226"
#define PORT 8888
void* SEND_to(void* arg);
void* RECV_from(void* arg);
//读和写的结构体定义
talk talk_to;
talk talk_from;
//全局的定义
int sfd = -1;
struct sockaddr_in cin;
socklen_t len = sizeof(cin);
struct sockaddr_in serin;
socklen_t len1 = sizeof(serin);
int main(int argc,const char * argv[])
{
//客户端
//udp连接创建报式字节套
sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0){
ERR_MSG("socket");
return -1;
}
//printf("%d\n",sfd);
//绑定
// struct sockaddr_in serin;
serin.sin_family = AF_INET;
serin.sin_port = htons(PORT);
serin.sin_addr.s_addr = inet_addr(IP);
// socklen_t len1 = sizeof(serin);
// struct sockaddr_in cin;
// socklen_t len = sizeof(cin);
//创建成功后之间分两步进程让两个进程分别读和写
pthread_t tid,tid1;
if((pthread_create(&tid,NULL,(void*)SEND_to,NULL)) < 0){
printf("error %d\n",__LINE__);
return -1;
}
if((pthread_create(&tid1,NULL,(void*)RECV_from,NULL)) < 0){
printf("error %d\n",__LINE__);
return -1;
}
pthread_join(tid,NULL);
pthread_detach(tid1);
pthread_join(tid1,NULL);
return 0;
}
//写
void* SEND_to(void* arg){
int res = 0;
char idname[20];
char a;
char buf[128] = "";
printf("请输入id>>>>");
scanf("%s",idname);
strcpy(talk_to.name,idname);
while(1){//划分线程
printf("请输入type(L,Q,C)>>>>\n");
scanf(" %c",&a);
talk_to.type = a;
memset(buf,0,sizeof(buf));
memset(talk_to.text,0,sizeof(talk_to.text));
strcpy(talk_to.text,buf);
if(!('q' == a||'Q' == a||'L' == a||'l' == a)){//只有聊天才使用输入话
printf("请输入test>>>>\n");
scanf("%s",buf);
strcpy(talk_to.text,buf);
}
//printf("type = %c name = %s text = %s\n",talk_to.type,talk_to.name,talk_to.text);
//printf("__%d__\n",__LINE__);
res = sendto(sfd,&talk_to,sizeof(talk_to),0,(struct sockaddr*)&serin,len1);
if(res < 0){
printf("error __%d__",__LINE__);
break;
}
if('Q' == a||'q' == a){
break;
}
}
pthread_exit(NULL);
}
//读
void* RECV_from(void* arg){
int res = 0;
usr_inf inf;
while(1){//读来自服务器的信息
res = recvfrom(sfd,&inf,sizeof(inf),0,NULL,NULL);
if(res < 0){
printf("error __%d__",__LINE__);
break;
}
//打印信息且只打印name和text
printf("%s:%s\n",inf.name,inf.text);
}
pthread_exit(NULL);
}