局域网聊天室

最近学习网络编程,写了一个聊天室,基本功能已经实现,还有待优化的部分

服务器端

首先说下大概的功能吧

1. 服务器开始运行,绑定好IP跟端口

2.服务器开始监听客户端的链接

3.如果有客户端链接服务器,那么服务器记录下客户端的地址,

   然后分配一个线程用于跟客户端通信

4.服务器把接受到的消息分别转发给其他客户端,实现共享聊天内容

4.1.服务器继续监听其他客户端的链接。

#include"server.h"
static int sockid,i,end;
void fa(int signo)
{
	printf("\r服务器正在关闭>>>>>\n");
	sleep(2);
	close(sockid);
	exit(0);
}
typedef struct
{
	struct sockaddr_in c_sockaddr;
	int c_sockid;
	pthread_t tid;
}c_addr;
//建立套接字绑定端口
int s_bind(void);
int s_pthread_create(int sockid);
void * task(void *p);

int main(int argc,char * agrv[])
{
	printf("服务器开始运行\n");
	//信号处理
	signal(2,fa);
	//建立套结字,绑定借口
	int sockid = s_bind();
	if(-1 == sockid)  
		printf("建立绑定套结字失败\n");		
	//开始监听客户端
	listen(sockid,100);
	//为客户端分配线程
	s_pthread_create(sockid);
	//exit(0);
	exit(0);
}
int s_bind(void)
{
	//生成套结字
	 sockid = socket(AF_INET,SOCK_STREAM,0);
	//准备地址信息
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	//绑定服务短地址
	int res = bind(sockid,(struct sockaddr *)&addr,sizeof(addr));
	if(res == -1)
	{
		perror("bind"),exit(-1);;
	}
	return sockid;
}

int s_pthread_create(int sockid)
{
	//定义结构题,用于存储客户端的地址与通信编号
	c_addr c_c_addr[100];
	while(i < 100){
		//初始化c_c_addr
		c_c_addr[i].c_sockid = 0;
	//准备套结字接收客户端地址
	socklen_t len = sizeof(c_c_addr[i].c_sockaddr);
	//接受到客户端信息
	c_c_addr[i].c_sockid = accept(sockid,(struct sockaddr *)&c_c_addr[i].c_sockaddr,&len);
	if(c_c_addr[i].c_sockid == -1)
		perror("accept"),exit(-1);
		//分配线程
		//pthread_t tid;
		
		printf("客户端:%s上线\n",inet_ntoa(c_c_addr[i].c_sockaddr.sin_addr));
		pthread_create(&c_c_addr[i].tid,NULL,task,(void *)c_c_addr);
		usleep(500000);
		i++;
	}
}
void * task(void *p) 
{
	int n = i;
		c_addr * c_c_addr = p;
     //接收客户端发来的消息
	 char buf[100] = {0};
	 while(1)
	 {

		printf("n == %d\n",n);
	 	if(0 >= read(c_c_addr[n].c_sockid,buf,sizeof(buf)))
		{				
				c_c_addr[n].c_sockid = -1;
				printf("客户端:%s下线\n",inet_ntoa(c_c_addr[n].c_sockaddr.sin_addr));
				pthread_exit(&c_c_addr[n].tid);
		}
		printf("来自客户端的消息%s\n",buf);
		char *p = buf;
		//转发给其他客户端
		int j = 0;
		while(j < i)
		{
			//判断是否是自己线程,
			if(c_c_addr[j].tid == pthread_self() || c_c_addr[j].c_sockid == -1)
			{
				j++;
				continue;
			}
			if(0 >= send(c_c_addr[j].c_sockid,buf,strlen(buf) + 1,0))
			{
				c_c_addr[j].c_sockid = -1;
			}
			j++;
		}
	 //推出线程
	 }	
}


客户端

1.客户端初始化链接服务器的地址

2.链接成功后客户端分配一个线程用于接受服务器

   发送来的消息

3.客户端主线程用于接收用户输入的内容发送给服务器

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<semaphore.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<pthread.h>
#include<unistd.h>
#define PORT 8888
int sockid;
void fa(int signo)
{
	printf("\r客户端马上关闭\n");
	close(sockid);
	sleep(1);
	exit(0);
}
int c_connect(void);
void scan(char arr[]);
void talk(void);
void *task(void *p);
void speak(char *name);
int main()
{
	signal(2,fa);
	//与服务器建立链接
	 sockid = c_connect();
	//输入用户昵称
	char name[20];
	printf("请输入用户姓名\n");
	scanf("%s",name);
        //接收服务器发来的消息
        talk();
        //吧用户输入的信息发送给服务器端
        speak(name);	
}
void speak(char *name)
{
	while(1)
	{
		//sleep(1);
		printf("请输入信息:\n");
		char cuf[100];
		fflush(stdin);
		//scanf("%*[^\n]");
		//scanf("%*c");
		//fwrite(cuf,1,1,stdin);
		scanf("%s",cuf);
	//	fgets(cuf,100,stdin);
		fflush(stdin);
		//cuf[strlen(cuf)-1] = '\0'; 
		char buf[1000];
		sprintf(buf,"%s:%s",name,cuf);
		int res;
		if( 0 >= send(sockid,buf,strlen(buf) + 1,0))
			//printf("res = %d\n",res);
			perror("服务器关闭"),exit(-1);
	}
}
void *task(void *p)
{
	char buf[100];
	while(1)
	{
		if(0 > recv(sockid,buf,sizeof(buf),0))
			perror("recv"),exit(0);
		printf("%s\n",buf);
	}
}
void talk(void)
{
	//创建线程用于接受服务器的消息
	pthread_t tid;
	pthread_create(&tid,NULL,task,NULL);
}
void scan(char arr[])
{
	printf("请输入用户昵称\n");
	scanf("%s",arr);
	fflush(stdin);
}
int c_connect(void)
{
	int sockid = socket(AF_INET,SOCK_STREAM,0);
	//准备服务器的地址信息
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8888);
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	//链接服务器地址
	int res = connect(sockid,(struct sockaddr*)&addr,sizeof(addr));
	if(-1 == res)
	{
		perror("connect"),exit(-1);
	}
	return sockid;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
因为太大,所以我压缩成7z格式了。 此课程设计包含三个主文件: ChatServer 聊天室服务端代码 Client 聊天室客户端代码 Bin 已编译程序 Web 聊天室浏览器端 配置如下: ①下载好Xampp并安装(http://sourceforge.net/projects/xampp/),然后将Web文件夹下的Chat文件夹里的内容复制到"Xampp安装目录\htdocs\Chat"目录下。 ②启动Xampp(包括Apache和MySql)。 ③打开http://服务器IP或者域名/PhpMyAdmin/并自行设置好连接用户名及密码。 ⑤新建数据库,库名为mfcchat。 ④进入mfcchat数据库点击“导入”,文件位置为Web目录下的MFCChat.sql。并点击执行以导入用户表。 ⑤打开Bin文件夹下的服务端文件夹,编辑ChatConf.ini文件,配置相应设置。 ⑥打开Client文件夹下的工程 1、编辑CClientDlg类下的InitChannel函数,编辑相应的频道信息。 2、编辑CClientDlg类下的OnInitDialog函数,找到ChannelListCtrl.SelectString(0, _T("风花雪月"));,改成默认频道名。 ⑦打开Client下Client文件夹,编辑ChatRoom.htm、Chatting.htm、RegisterDlg.htm,将里面所有IP地址替换成Xampp所在的主机的IP或者域名。 ⑧重新生成Client工程。 ⑨生成的客户端在Client\Client\Bin目录下,复制到"Bin\服务端"文件夹下即可。 最后打开"Bin\服务端"下的可执行文件即可开启聊天服务。然后把"Bin\客户端"分发出去即可使用。 注意:最新的版本由于加了监听实时在线功能,所以导致很多自己解决不了的BUG。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值