0811网络编程day3

 服务器

#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;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值