Linux C 网络编程——多线程的聊天室实现(服务器端)
服务器端的主要功能:
实现多用户群体聊天功能(此程序最多设定为10人,可进行更改),每个人所发送的消息其他用户均可以收到。用户可以随意的加入或退出(推出以字符串“bye”实现),服务器也可以进行关闭。
服务器端的程序结构:
总共有三个函数:主函数(main),实现服务器端的初始化,接受连接;消息处理函数(rcv_snd),接受某一用户的消息,将其进行简单处理之后发送给其他所有的用户;退出函数(quit),可实现服务器关停。
这三个函数分别从属于三个线程(准确说是大于等于三个,下面说明原因):main函数的作为诛仙程线程,又创建了一个退出函数所在的线程,以及每次接受到一个连接之后会新创建一个对此连接的消息进行处理的线程(多于三个的原因在此)。
具体代码实现如下:
- #include<time.h>
- #include<stdio.h>
- #include<sys/socket.h>
- #include<netinet/in.h>
- #include<string.h>
- #define LISTENQ 5
- #define MAXLINE 512
- #define MAXMEM 10
- #define NAMELEN 20
- int listenfd,connfd[MAXMEM];//分别记录服务器端的套接字与连接的多个客户端的套接字
- void quit();//服务器关闭函数
- void rcv_snd(int n);//服务器接收并转发消息函数
- int main()
- {
- pthread_t thread;
- struct sockaddr_in servaddr,cliaddr;
- socklen_t len;
- time_t ticks;
- char buff[MAXLINE];
- //调用socket函数创建服务器端的套接字
- printf("Socket...\n");
- listenfd=socket(AF_INET,SOCK_STREAM,0);
- if(listenfd<0)
- {
- printf("Socket created failed.\n");
- return -1;
- }
- //调用bind函数使得服务器端的套接字与地址实现绑定
- printf("Bind...\n");
- servaddr.sin_family=AF_INET;
- servaddr.sin_port=htons(6666);
- servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
- if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
- {
- printf("Bind failed.\n");
- return -1;
- }
- //调用listen函数,将一个主动连接套接字变为被动的倾听套接字
- //在此过程中完成tcp的三次握手连接
- printf("listening...\n");
- listen(listenfd,LISTENQ);
- //创建一个线程,对服务器程序进行管理(关闭)
- pthread_create(&thread,NULL,(void*)(&quit),NULL);
- //记录空闲的客户端的套接字描述符(-1为空闲)
- int i=0;
- for(i=0;i<MAXMEM;i++)
- {
- connfd[i]=-1;
- }
- while(1)
- {
- len=sizeof(cliaddr);
- for(i=0;i<MAXMEM;i++)
- {
- if(connfd[i]==-1)
- {
- break;
- }
- }
- //调用accept从listen接受的连接队列中取得一个连接
- connfd[i]=accept(listenfd,(struct sockaddr*)&cliaddr,&len);
- ticks=time(NULL);
- sprintf(buff,"% .24s \r \n",ctime(&ticks));
- printf("%s Connect from: %s,port %d\n\n",buff,inet_ntoa(cliaddr.sin_addr.s_addr),ntohs(cliaddr.sin_port));
- //针对当前套接字创建一个线程,对当前套接字的消息进行处理
- pthread_create(malloc(sizeof(pthread_t)),NULL,(void*)(&rcv_snd),(void*)i);
- }
- return 0;
- }
- void quit()
- {
- char msg[10];
- while(1)
- {
- scanf("%s",msg);
- if(strcmp("quit",msg)==0)
- {
- printf("Byebye...\n");
- close(listenfd);
- exit(0);
- }
- }
- }
- void rcv_snd(int n)
- {
- char* ask="Your name please:";
- char buff[MAXLINE];
- char buff1[MAXLINE];
- char buff2[MAXLINE];
- char name[NAMELEN];
- time_t ticks;
- int i=0;
- int retval;
- //获取此进程对应的套接字用户的名字
- write(connfd[n],ask,strlen(ask));
- int len;
- len=read(connfd[n],name,NAMELEN);
- if(len>0)
- {
- name[len]=0;
- }
- //把当前用户的加入告知所有用户
- strcpy(buff,name);
- strcat(buff,"\tjoin in\0");
- for(i=0;i<MAXMEM;i++)
- {
- if(connfd[i]!=-1)
- {
- write(connfd[i],buff,strlen(buff));
- }
- }
- //接受当前用户的信息并将其转发给所有的用户
- while(1)
- {
- if((len=read(connfd[n],buff1,MAXLINE))>0)
- {
- buff1[len]=0;
- //当当前用户的输入信息为“bye”时,当前用户退出
- if(strcmp("bye",buff)==0)
- {
- close(connfd[n]);
- connfd[n]=-1;
- pthread_exit(&retval);
- }
- ticks=time(NULL);
- sprintf(buff2,"%.24s\r\n",ctime(&ticks));
#include<time.h>
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#define LISTENQ 5
#define MAXLINE 512
#define MAXMEM 10
#define NAMELEN 20
int listenfd,connfd[MAXMEM];//分别记录服务器端的套接字与连接的多个客户端的套接字
void quit();//服务器关闭函数
void rcv_snd(int n);//服务器接收并转发消息函数
int main()
{
pthread_t thread;
struct sockaddr_in servaddr,cliaddr;
socklen_t len;
time_t ticks;
char buff[MAXLINE];
//调用socket函数创建服务器端的套接字
printf("Socket...\n");
listenfd=socket(AF_INET,SOCK_STREAM,0);
if(listenfd<0)
{
printf("Socket created failed.\n");
return -1;
}
//调用bind函数使得服务器端的套接字与地址实现绑定
printf("Bind...\n");
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(6666);
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
{
printf("Bind failed.\n");
return -1;
}
//调用listen函数,将一个主动连接套接字变为被动的倾听套接字
//在此过程中完成tcp的三次握手连接
printf("listening...\n");
listen(listenfd,LISTENQ);
//创建一个线程,对服务器程序进行管理(关闭)
pthread_create(&thread,NULL,(void*)(&quit),NULL);
//记录空闲的客户端的套接字描述符(-1为空闲)
int i=0;
for(i=0;i<MAXMEM;i++)
{
connfd[i]=-1;
}
while(1)
{
len=sizeof(cliaddr);
for(i=0;i<MAXMEM;i++)
{
if(connfd[i]==-1)
{
break;
}
}
//调用accept从listen接受的连接队列中取得一个连接
connfd[i]=accept(listenfd,(struct sockaddr*)&cliaddr,&len);
ticks=time(NULL);
sprintf(buff,"% .24s \r \n",ctime(&ticks));
printf("%s Connect from: %s,port %d\n\n",buff,inet_ntoa(cliaddr.sin_addr.s_addr),ntohs(cliaddr.sin_port));
//针对当前套接字创建一个线程,对当前套接字的消息进行处理
pthread_create(malloc(sizeof(pthread_t)),NULL,(void*)(&rcv_snd),(void*)i);
}
return 0;
}
void quit()
{
char msg[10];
while(1)
{
scanf("%s",msg);
if(strcmp("quit",msg)==0)
{
printf("Byebye...\n");
close(listenfd);
exit(0);
}
}
}
void rcv_snd(int n)
{
char* ask="Your name please:";
char buff[MAXLINE];
char buff1[MAXLINE];
char buff2[MAXLINE];
char name[NAMELEN];
time_t ticks;
int i=0;
int retval;
//获取此进程对应的套接字用户的名字
write(connfd[n],ask,strlen(ask));
int len;
len=read(connfd[n],name,NAMELEN);
if(len>0)
{
name[len]=0;
}
//把当前用户的加入告知所有用户
strcpy(buff,name);
strcat(buff,"\tjoin in\0");
for(i=0;i<MAXMEM;i++)
{
if(connfd[i]!=-1)
{
write(connfd[i],buff,strlen(buff));
}
}
//接受当前用户的信息并将其转发给所有的用户
while(1)
{
if((len=read(connfd[n],buff1,MAXLINE))>0)
{
buff1[len]=0;
//当当前用户的输入信息为“bye”时,当前用户退出
if(strcmp("bye",buff)==0)
{
close(connfd[n]);
connfd[n]=-1;
pthread_exit(&retval);
}
ticks=time(NULL);
sprintf(buff2,"%.24s\r\n",ctime(&ticks));
- strcpy(buff,name);
- strcat(buff,"\t");
- strcat(buff,buff2);
- strcat(buff,buff1);
- for(i=0;i<MAXMEM;i++)
- {
- if(connfd[i]!=-1)
- {
- write(connfd[i],buff,strlen(buff));
- }
- }
- }
- }
Linux C 网络编程——多线程的聊天室实现(服务器端)的更多相关文章
- Linux C 网络编程——多线程的聊天室实现(server端)
server端的主要功能: 实现多用户群体聊天功能(此程序最多设定为10人.可进行更改),每一个人所发送的消息其它用户均能够收到.用户能够任意的增加或退出(推出以字符串"bye"实 ...
- 网络编程TCP协议-聊天室
网络编程TCP协议-聊天室(客户端与服务端的交互); <span style="font-size:18px;">1.客户端发数据到服务端.</span> ...
- 使用Android网络编程实现简易聊天室
在Java中我们可以利用socket编程实现聊天室,在Android中也一样,因为Android完全支持JDK本身的TCP.UDP网络通信API.我们可以使用ServerSocket.Socket来建 ...
- 网络编程-基于Websocket聊天室(IM)系统
目录 一.HTML5 - Websocket协议 二.聊天室(IM)系统的设计 2.1.使用者眼中的聊天系统 2.2.开发者眼中的聊天系统 2.3.IM系统的特性 2.4.心跳机制:解决网络的不确定性 ...
- 嵌入式linux的网络编程(1)--TCP/IP协议概述
嵌入式linux的网络编程(1)--TCP/IP协议概述 1.OSI参考模型及TCP/IP参考模型 通信协议用于协调不同网络设备之间的信息交换,它们建立了设备之间互相识别的信息机制.大家一定都听说过著 ...
- Linux C网络编程学习笔记
Linux C网络编程总结报告 一.Linux C 网络编程知识介绍: 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端:(client) 在网络程序中, ...
- Linux C++ 网络编程学习系列(1)——端口复用实现
Linux C++ 网络编程学习系列(1)--端口复用实现 源码地址:https://github.com/whuwzp/linuxc/tree/master/portreuse 源码说明: serv ...
- Linux&C网络编程————“聊天室”
从上周到现在一直在完成最后的项目,自己的聊天室,所以博客就没怎么跟了,今天晚上自己的聊天室基本实现,让学长检查了,也有好些bug,自己还算满意,主要实现的功能有: 登录注册 附近的人(服务器端全部在线 ...
- Linux&C网络编程————“聊天室”
从上周到现在一直在完成最后的项目,自己的聊天室,所以博客就没怎么跟了,今天晚上自己的聊天室基本实现,让学长检查了,也有好些bug,自己还算满意,主要实现的功能有: 登录注册 附近的人(服务器端全部在线 ...
随机推荐
- Tinyhttpd for Windows(500多行)
TinyHTTPd forWindows 前言 TinyHTTPd是一个开源的简易学习型的HTTP服务器,项目主页在:http://tinyhttpd.sourceforge.NET/,源代码下载:h ...
- 孟岩:技术路线的选择重要但不具有决定性(什么是核心竞争力?是你独特的个性知识经验组合,正确的态度应该是着重于你要干的事情,然后认真把这件事情做好,然后融会贯通)good
转自 http://blog.csdn.net/myan/article/details/3247071 孟岩 2008 年的文章,现在看来还是挺有启发, 送给大家,也送给自己. 最近微软在技术上 ...
- 15个非常棒的jQuery无限滚动插件【瀑布流效果】
现在,最热门的网站分页趋势之一是jQuery的无限滚动(也即瀑布流).如果你碰巧观察Pinterest的网站,如Facebook,Twitter和deviantART的,你会发现无限滚动的动作,当旧的 ...
- play框架之简介
Play Framework是一个开源的Web框架,背后商业公司是Typesafe.要介绍Play之前,首先理清Play的两个不同的分支. Play 1.x 使用Java开发,最新版本是1.3.1,只 ...
- win10 下的YOLOv3 训练 wider_face 数据集检测人脸
1.数据集下载 (1)wider_face 数据集网址为 http://shuoyang1213.me/WIDERFACE/index.html 下载以上几项文件(这里推荐 google Drive ...
- Vue.js 面试题整理
Vue项目结构介绍 build 文件夹:用于存放 webpack 相关配置和脚本. config 文件夹:主要存放配置文件,比如配置开发环境的端口号.开启热加载或开启gzip压缩等. dist 文件夹 ...
- 原创-使用pywinauto进行dotnet的winform程序控制(一)
pywinauto自动化控制win32的ui的程序,网上有好多的教程.但是操作dotnet写的winform教程,就少之又少.今天我就来分享我的pywinauto操作dotnet的winform的研究 ...
- kafka 名词概念
ProducerConsumerBrokerTopicPartitionConsumer Group分布式 Broker Kafka集群包含一个或多个服务器,这种服务器被称为brokerTop ...
- 【前端工具】页面加载获取url param
例如跳转进入一个页面: https://mp.csdn.net/postedit/74766644?name=catalina&flag=1 函数: function getParam(par ...
- 编译php扩展
在php编译安装好的情况下php扩展编译 php的很多模块都是以php的扩展形式来进行的.所以在php安装好的环境下需要用到之前安装时没有编译安装的php扩展的时候,这个时候编译安装php扩展就显得尤 ...