您的位置:首页 > 理论基础 > 计算机网络

Linux网络编程(多人在线聊天系统)

2014-07-20 21:07 155 查看
一、首先是服务器的建立

首先是一个信号终止程序,发信号ctrl+c终止程序,而是是初始化网络通信.

创建一个描述符负责绑定服务器和监听服务器接收客户端的消息.

socket()->sockaddr_in->bind->listen(准备就绪)

开始接收客户端消息.start()函数

首先是声明一个结构体用来存储客户端的消息,利用accept()函数来创建一个新的

描述符来接收,这里有阻塞效果,也即是说连接的时候只能一个一个的连.

然后是分离线程处理这个sockfd的连接.

pthread_create(&pid,0,pthread_deal,&sockfd1);

线程主要是先做线程的分离,然后是取得它们的sockfd描述符,把这个客户端的信息

存储到一个结构体数组中.然后是调用循环发送到各个客户端的函数,来发送消息.

当接收函数recv(sockfd,buf,sizeof(buf)) == 0 的时候,表示有客户端退出,这时

就把这个在结构体数组的相应的fd置为0

#include "server.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

int sockfd; //服务器本身的描述符
struct User u[200] = {}; //用来保存用户的信息
int size;//数组的下标,同时也是客户端的个数

void init(void) //通信准备工作
{
printf("聊天室服务器马上启动....\n");
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == sockfd)
{
perror("fail to socket");
printf("服务器故障!\n");
exit(-1);
}
//准备通信地址和绑定服务器
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(2222); //端口的值,转换成网络的格式
addr.sin_addr.s_addr = inet_addr("172.16.1.21");
if(-1 == bind(sockfd,(struct sockaddr*)&addr,sizeof(addr)))
{
perror("fail to bind");
exit(-1);
}
printf("bind is ok,欢迎访问!\n");
//设置监听
if(-1 != listen(sockfd,200))
{
printf("监听已经设置,一切准备就绪!\n");
}
}

void send_msg(char *p_msg) //发送消息的函数
{
int num = 0;
for(num = 0;num < size;num++)
{
if(u[num].fd) //如果是有效的时候才发送
{
send(u[num].fd,p_msg,sizeof(p_msg),0);
}
}
}

void* pthread_deal(void* p) //线程处理函数
{
pthread_detach(pthread_self());
int fd2 = *(int*)p; //取得客户端的sockfd
u[size].fd = fd2;  //放入结构体中
char name[20] = {};
int res = recv(fd2,name,sizeof(name),0);
if(res > 0)
{
strcpy(u[size].name,name);//存放用户名
}
size++;
char user[100] = {};
sprintf(user,"%s悄悄的进来了!(*^__^*) 嘻嘻……\n",name);
send_msg(user);
while(1)
{
if(recv(fd2,name,sizeof(name),0) == 0) /*返回0表示有客户端退出*/
{
u[size-1].fd = 0; //把退出的客户端的结构描述符置换成0
}
}
}

void start(void)
{
printf("success to start server,let's go!\n");
while(1)
{
struct sockaddr_in client;//存储接收到的客户端的信息
socklen_t length = sizeof(client);
//接收客户端的信息,会有阻塞效果,sockfd1标记客户端
int sockfd1 = accept(sockfd,(struct sockaddr*)&client,&length);
if(sockfd1 == -1)
{
perror("fail to accept!");
continue;  //继续连接
}
printf("%s连接上来了\n",inet_ntoa(client.sin_addr));
/*连接成功之后,就启动线程*/
pthread_t pid;//线程id
pthread_create(&pid,0,pthread_deal,&sockfd1);
}
}

void sig_exit(int signo ) //子定义信号关闭服务器函数
{
close(sockfd);//关闭服务器端口
printf("服务器成功关闭!\n");
exit(0);
}
int main(void)
{
printf("按ctrl+c关闭聊天室服务器!\n");
signal(SIGINT,sig_exit);
init();//初始化,服务器通信准备工作
start();//启动服务(开始处理聊天信息)
return 0;
}


2.客户端的编写.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: