Linux C 网络编程——多线程的聊天室实现(server端)
server端的主要功能:
实现多用户群体聊天功能(此程序最多设定为10人。可进行更改),每一个人所发送的消息其它用户均能够收到。用户能够任意的增加或退出(推出以字符串“bye”实现),server也能够进行关闭。
server端的程序结构:
总共同拥有三个函数:主函数(main),实现server端的初始化,接受连接;消息处理函数(rcv_snd),接受某一用户的消息。将其进行简单处理之后发送给其它全部的用户;退出函数(quit),可实现server关停。
这三个函数分别从属于三个线程(准确说是大于等于三个,以下说明原因):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];//分别记录server端的套接字与连接的多个client的套接字
- void quit();//server关闭函数
- void rcv_snd(int n);//server接收并转发消息函数
- int main()
- {
- pthread_t thread;
- struct sockaddr_in servaddr,cliaddr;
- socklen_t len;
- time_t ticks;
- char buff[MAXLINE];
- //调用socket函数创建server端的套接字
- printf("Socket...\n");
- listenfd=socket(AF_INET,SOCK_STREAM,0);
- if(listenfd<0)
- {
- printf("Socket created failed.\n");
- return -1;
- }
- //调用bind函数使得server端的套接字与地址实现绑定
- 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);
- //创建一个线程。对server程序进行管理(关闭)
- pthread_create(&thread,NULL,(void*)(&quit),NULL);
- //记录空暇的client的套接字描写叙述符(-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];//分别记录server端的套接字与连接的多个client的套接字 void quit();//server关闭函数
void rcv_snd(int n);//server接收并转发消息函数 int main()
{
pthread_t thread;
struct sockaddr_in servaddr,cliaddr;
socklen_t len;
time_t ticks;
char buff[MAXLINE]; //调用socket函数创建server端的套接字
printf("Socket...\n");
listenfd=socket(AF_INET,SOCK_STREAM,0);
if(listenfd<0)
{
printf("Socket created failed.\n");
return -1;
} //调用bind函数使得server端的套接字与地址实现绑定
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); //创建一个线程,对server程序进行管理(关闭)
pthread_create(&thread,NULL,(void*)(&quit),NULL); //记录空暇的client的套接字描写叙述符(-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 网络编程——多线程的聊天室实现(server端)的更多相关文章
- Linux C 网络编程——多线程的聊天室实现(服务器端)
服务器端的主要功能: 实现多用户群体聊天功能(此程序最多设定为10人,可进行更改),每个人所发送的消息其他用户均可以收到.用户可以随意的加入或退出(推出以字符串"bye"实现),服 ...
- 网络编程TCP协议-聊天室
网络编程TCP协议-聊天室(客户端与服务端的交互); <span style="font-size:18px;">1.客户端发数据到服务端.</span> ...
- 网络编程-基于Websocket聊天室(IM)系统
目录 一.HTML5 - Websocket协议 二.聊天室(IM)系统的设计 2.1.使用者眼中的聊天系统 2.2.开发者眼中的聊天系统 2.3.IM系统的特性 2.4.心跳机制:解决网络的不确定性 ...
- 使用Android网络编程实现简易聊天室
在Java中我们可以利用socket编程实现聊天室,在Android中也一样,因为Android完全支持JDK本身的TCP.UDP网络通信API.我们可以使用ServerSocket.Socket来建 ...
- 嵌入式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,自己还算满意,主要实现的功能有: 登录注册 附近的人(服务器端全部在线 ...
随机推荐
- C语言指针的理解以及指针的指针的理解
指针指向的是内存地址编号,内存地址编号指向的是对应的内容. 我们需要一个变量,来储存内存地址编号,这个变量的值是一个内存地址编号,但是我们可以通过修改变量的值,来不断的改变内存地址编号. 但是,我们如 ...
- Python批量下载电视剧电影--自己动手丰衣足食
前言 为了看美剧<天蝎>,在电影天堂找到了,于是就想下载下来好好欣赏. 废话不说了,直接上代码. 代码 import requests,re,os,time url = "htt ...
- 并发编程学习笔记(8)----ThreadLocal的使用及源码分析
1. ThreadLocal的理解 ThreadLocal,顾名思义,就是线程的本地变量,ThreadLocal会为每个线程创建一个本地变量副本,使得使用ThreadLocal管理的变量在多线程的环境 ...
- RocketMQ学习笔记(13)----RocketMQ的Consumer消息重试
1. 概念 Producer端重试: 生产者端的消息失败,也就是Producer往MQ上发消息没有发送成功,比如网络抖动导致生产者发送消息到MQ失败. 这种消息失败重试我们可以手动设置发送失败重试的次 ...
- WINVER WIN32 WINNT
WINVER 和 _WIN32_WINNT 请在WINDOWS.H前定义 从 Visual C++ 2008 开始,Visual C++ 不支持面向 Windows 95.Windows 98.Win ...
- VMware vCenter 6.5 安装及群集配置介绍
一.介绍 VMware vCenter Server 提供了一个可伸缩.可扩展的平台,为虚拟化管理奠定了基础.可集中管理VMware vSphere环境,与其他管理平台相比,极大地提高了 IT 管理员 ...
- CAD在一个点构造选择集
主要用到函数说明: IMxDrawSelectionSet::SelectAtPoint 在一个点构造选择集.详细说明如下: 参数 说明 [in] IMxDrawPoint* point 点坐标 [i ...
- 【转】上传并解析excel
[转载自]http://blog.csdn.net/u011563331/article/details/51322523 通过解析excel,将数据存储到数据库中.现在将方法保存下来. 使用的是ap ...
- HDU5834 Magic boy Bi Luo with his excited tree (树形DP)
题意:一棵树有点权和边权 从每个点出发 走过一条边要花费边权同时可以获得点权 边走几次就算几次花费 点权最多算一次 问每个点能获得的最大价值 题解:好吧 这才叫树形DP入门题 dp[i][0]表示从i ...
- BZOJ 1058: [ZJOI2007]报表统计 multiset + 卡常
Code: #include<bits/stdc++.h> #define maxn 600000 #define inf 1000000000 using namespace std; ...