服务器
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
//打印错误宏函数
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define PORT 8888
#define IP "192.168.31.228"
typedef uint16_t datatype;
//链表结构体
typedef struct Node
{
union{
datatype data;
int len;
};
struct Node *next;
struct Node *pro;
}cport;
//创建存储链表
cport *list_create()
{
cport *l=(cport *)malloc(sizeof(cport));
if(NULL==l)
{
printf("创建失败\n");
return NULL;
}
l->len=0;
l->pro=NULL;
l->next=NULL;
return l;
}
//判空
int list_empty(cport *l)
{
return l->len==0?1:0;
}
//申请节点存放数据
cport *node_buy(datatype data)
{
cport *p=(cport*)malloc(sizeof(cport));
if(NULL==p)
{
printf("申请失败\n");
return NULL;
}
p->data=data;
p->next=NULL;
p->pro=NULL;
return p;
}
//遍历链表
int list_show(cport *l,datatype data)
{
if(NULL==l)
{
return-1;
}
if(list_empty(l))
{
cport *p=node_buy(data);
p->pro=l;
l->next=p;
l->len++;
}
else
{
cport*q=l->next;
while(q!=NULL)
{
if(data==q->data)
return 1;
q=q->next;
}
cport *r=node_buy(data);
r->next=l->next;
r->pro=l;
r->next->pro=r;
l->next=r;
l->len++;
return 2;
}
return 0;
}
//删除操作
void list_del(cport *l,datatype data)
{
if(NULL==l)
{
return;
}
cport *q=l->next;
while(q!=NULL)
{
if(q->data==data)
{
if(q->next==NULL)
{
q->pro->next=NULL;
free(q);
q=NULL;
l->len--;
}
else
{
q->pro->next=q->next;
q->next->pro=q->pro;
free(q);
q=NULL;
l->len--;
}
return;
}
q=q->next;
}
}
int sfd;
cport *l;
//发送系统消息的线程
void *se_nd(void *arg)
{
struct sockaddr_in snd_sys;
snd_sys.sin_family=AF_INET;
snd_sys.sin_addr.s_addr=inet_addr(IP);
socklen_t addrlen=sizeof(snd_sys);
char buf[128]="";
while(1)
{
char sys[150]="system:";
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
strcat(sys,buf);
strcpy(buf,sys);
cport *q=l->next;
while(q!=NULL)
{
snd_sys.sin_port=htons(q->data);
if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr *)&snd_sys,addrlen)<0)
{
ERR_MSG("sendto");
return NULL;
}
q=q->next;
}
}
}
int main(int argc, const char *argv[])
{
//创建报式套接字
sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
//填充服务器的IP地址以及端口号
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port =htons(PORT);
sin.sin_addr.s_addr =inet_addr(IP);
//绑定IP地址和端口号
if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
{
ERR_MSG("bind");
return -1;
}
//存储接收到的数据包来自哪里
struct sockaddr_in rcv_msg;
socklen_t addrlen=sizeof(rcv_msg);
//发送出去的数据包
struct sockaddr_in snd_msg;
snd_msg.sin_family=AF_INET;
snd_msg.sin_addr.s_addr=inet_addr(IP);
socklen_t addrlen2=sizeof(snd_msg);
//接收数据的双向链表
l=list_create();
if(NULL ==l)
{
printf("创建失败\n");
return -1;
}
char buf[128]="";
char name[10]="";
pthread_t td;
pthread_create(&td,NULL,se_nd,NULL);
while(1)
{
bzero(buf,sizeof(buf));
if(recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr *)&rcv_msg,&addrlen)<0)
{
ERR_MSG("recvfrom");
return -1;
}
printf("%d:%s\n",ntohs(rcv_msg.sin_port),buf);
//printf("[%s:%d]:%s\n",inet_ntoa(rcv_addrmsg.sin_addr),ntohs(rcv_addrmsg.sin_port),buf);
cport *q=l->next;
switch(list_show(l,ntohs(rcv_msg.sin_port)))
{
//聊天室内已有这个成员
case 1:
//如果发送过来的不是退出,就加上端口号发给除它的所有人
if(strcmp("quit",buf)!=0)
{
sprintf(name,"%d%c",ntohs(rcv_msg.sin_port),':');
strcat(name,buf);
strcpy(buf,name);
}
//如果发送过来的是退出,就删除它并加上端口号并发信息给除它以外的所有人
else if(strcmp("quit",buf)==0)
{
sprintf(name,"%d",ntohs(rcv_msg.sin_port));
strcpy(buf,name);
strcat(buf,"已退出");
//删除操作
list_del(l,ntohs(rcv_msg.sin_port));
}
while(q!=NULL)
{
if(q->data==ntohs(rcv_msg.sin_port))
{
q=q->next;
continue;
}
snd_msg.sin_port=htons(q->data);
if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr *)&snd_msg,addrlen2)<0)
{
ERR_MSG("sendto");
return -1;
}
q=q->next;
}
break;
//聊天室内的新成员
case 2:
strcat(buf,"已登陆");
while(q!=NULL)
{
if(q->data==rcv_msg.sin_port)
continue;
snd_msg.sin_port=htons(q->data);
if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&snd_msg,addrlen2)<0)
{
ERR_MSG("sendto");
return -1;
}
q=q->next;
}
break;
}
}
close(sfd);
return 0;
}
客户端
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
//打印错误宏函数
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define PORT 6667
#define IP "192.168.31.228"
int sfd;
void *re_ad(void *arg)
{
char buf[128]="";
while(1)
{
bzero(buf,sizeof(buf));
if(recvfrom(sfd,buf,sizeof(buf),0,NULL,NULL)<0)
{
ERR_MSG("recvfrom");
return NULL;
}
printf("%s\n",buf);
}
}
int main(int argc, const char *argv[])
{
//创建报式套接字
sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
//填充客户端的IP地址以及端口号
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port =htons(PORT);
sin.sin_addr.s_addr =inet_addr(IP);
//绑定IP地址和端口号
if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
{
ERR_MSG("bind");
return -1;
}
//存储接收到的数据包来自哪里
//填充服务器的IP地址以及端口号
struct sockaddr_in cin;
cin.sin_family=AF_INET;
cin.sin_port =htons(8888);
cin.sin_addr.s_addr =inet_addr(IP);
//连接到服务器
if(connect(sfd,(struct sockaddr *)&cin,sizeof(cin))<0)
{
ERR_MSG("connect");
return -1;
}
printf("连接到服务器成功\n您的端口是%d,请输入端口",PORT);
//创建读取进程
pthread_t td;
pthread_create(&td,NULL,re_ad,NULL);
char buf[128]="";
while(1)
{
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
if(sendto(sfd,buf,sizeof(buf),0,NULL,0)<0)
{
ERR_MSG("sendto");
return -1;
}
if(strcmp("quit",buf)==0)
exit(0);
}
close(sfd);
return 0;
}