server端的主要功能:

实现多用户群体聊天功能(此程序最多设定为10人。可进行更改),每一个人所发送的消息其它用户均能够收到。用户能够任意的增加或退出(推出以字符串“bye”实现),server也能够进行关闭。

server端的程序结构:

总共同拥有三个函数:主函数(main),实现server端的初始化,接受连接;消息处理函数(rcv_snd),接受某一用户的消息。将其进行简单处理之后发送给其它全部的用户;退出函数(quit),可实现server关停。

这三个函数分别从属于三个线程(准确说是大于等于三个,以下说明原因):main函数的作为诛仙程线程。又创建了一个退出函数所在的线程,以及每次接受到一个连接之后会新创建一个对此连接的消息进行处理的线程(多于三个的原因在此)。

详细代码实现例如以下:

  1. #include<time.h>
  2. #include<stdio.h>
  3. #include<sys/socket.h>
  4. #include<netinet/in.h>
  5. #include<string.h>
  6. #define LISTENQ 5
  7. #define MAXLINE 512
  8. #define MAXMEM 10
  9. #define NAMELEN 20
  10. int listenfd,connfd[MAXMEM];//分别记录server端的套接字与连接的多个client的套接字
  11. void quit();//server关闭函数
  12. void rcv_snd(int n);//server接收并转发消息函数
  13. int main()
  14. {
  15. pthread_t thread;
  16. struct sockaddr_in servaddr,cliaddr;
  17. socklen_t len;
  18. time_t ticks;
  19. char buff[MAXLINE];
  20. //调用socket函数创建server端的套接字
  21. printf("Socket...\n");
  22. listenfd=socket(AF_INET,SOCK_STREAM,0);
  23. if(listenfd<0)
  24. {
  25. printf("Socket created failed.\n");
  26. return -1;
  27. }
  28. //调用bind函数使得server端的套接字与地址实现绑定
  29. printf("Bind...\n");
  30. servaddr.sin_family=AF_INET;
  31. servaddr.sin_port=htons(6666);
  32. servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
  33. if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
  34. {
  35. printf("Bind failed.\n");
  36. return -1;
  37. }
  38. //调用listen函数,将一个主动连接套接字变为被动的倾听套接字
  39. //在此过程中完毕tcp的三次握手连接
  40. printf("listening...\n");
  41. listen(listenfd,LISTENQ);
  42. //创建一个线程。对server程序进行管理(关闭)
  43. pthread_create(&thread,NULL,(void*)(&quit),NULL);
  44. //记录空暇的client的套接字描写叙述符(-1为空暇)
  45. int i=0;
  46. for(i=0;i<MAXMEM;i++)
  47. {
  48. connfd[i]=-1;
  49. }
  50. while(1)
  51. {
  52. len=sizeof(cliaddr);
  53. for(i=0;i<MAXMEM;i++)
  54. {
  55. if(connfd[i]==-1)
  56. {
  57. break;
  58. }
  59. }
  60. //调用accept从listen接受的连接队列中取得一个连接
  61. connfd[i]=accept(listenfd,(struct sockaddr*)&cliaddr,&len);
  62. ticks=time(NULL);
  63. sprintf(buff,"% .24s \r \n",ctime(&ticks));
  64. printf("%s Connect from: %s,port %d\n\n",buff,inet_ntoa(cliaddr.sin_addr.s_addr),ntohs(cliaddr.sin_port));
  65. //针对当前套接字创建一个线程,对当前套接字的消息进行处理
  66. pthread_create(malloc(sizeof(pthread_t)),NULL,(void*)(&rcv_snd),(void*)i);
  67. }
  68. return 0;
  69. }
  70. void quit()
  71. {
  72. char msg[10];
  73. while(1)
  74. {
  75. scanf("%s",msg);
  76. if(strcmp("quit",msg)==0)
  77. {
  78. printf("Byebye...\n");
  79. close(listenfd);
  80. exit(0);
  81. }
  82. }
  83. }
  84. void rcv_snd(int n)
  85. {
  86. char* ask="Your name please:";
  87. char buff[MAXLINE];
  88. char buff1[MAXLINE];
  89. char buff2[MAXLINE];
  90. char name[NAMELEN];
  91. time_t ticks;
  92. int i=0;
  93. int retval;
  94. //获取此进程相应的套接字用户的名字
  95. write(connfd[n],ask,strlen(ask));
  96. int len;
  97. len=read(connfd[n],name,NAMELEN);
  98. if(len>0)
  99. {
  100. name[len]=0;
  101. }
  102. //把当前用户的增加告知全部用户
  103. strcpy(buff,name);
  104. strcat(buff,"\tjoin in\0");
  105. for(i=0;i<MAXMEM;i++)
  106. {
  107. if(connfd[i]!=-1)
  108. {
  109. write(connfd[i],buff,strlen(buff));
  110. }
  111. }
  112. //接受当前用户的信息并将其转发给全部的用户
  113. while(1)
  114. {
  115. if((len=read(connfd[n],buff1,MAXLINE))>0)
  116. {
  117. buff1[len]=0;
  118. //当当前用户的输入信息为“bye”时,当前用户退出
  119. if(strcmp("bye",buff)==0)
  120. {
  121. close(connfd[n]);
  122. connfd[n]=-1;
  123. pthread_exit(&retval);
  124. }
  125. ticks=time(NULL);
  126. 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));
  1. strcpy(buff,name);
  2. strcat(buff,"\t");
  3. strcat(buff,buff2);
  4. strcat(buff,buff1);
  5. for(i=0;i<MAXMEM;i++)
  6. {
  7. if(connfd[i]!=-1)
  8. {
  9. write(connfd[i],buff,strlen(buff));
  10. }
  11. }
  12. }
  13. }

Linux C 网络编程——多线程的聊天室实现(server端)的更多相关文章

  1. Linux C 网络编程——多线程的聊天室实现(服务器端)

    服务器端的主要功能: 实现多用户群体聊天功能(此程序最多设定为10人,可进行更改),每个人所发送的消息其他用户均可以收到.用户可以随意的加入或退出(推出以字符串"bye"实现),服 ...

  2. 网络编程TCP协议-聊天室

    网络编程TCP协议-聊天室(客户端与服务端的交互); <span style="font-size:18px;">1.客户端发数据到服务端.</span> ...

  3. 网络编程-基于Websocket聊天室(IM)系统

    目录 一.HTML5 - Websocket协议 二.聊天室(IM)系统的设计 2.1.使用者眼中的聊天系统 2.2.开发者眼中的聊天系统 2.3.IM系统的特性 2.4.心跳机制:解决网络的不确定性 ...

  4. 使用Android网络编程实现简易聊天室

    在Java中我们可以利用socket编程实现聊天室,在Android中也一样,因为Android完全支持JDK本身的TCP.UDP网络通信API.我们可以使用ServerSocket.Socket来建 ...

  5. 嵌入式linux的网络编程(1)--TCP/IP协议概述

    嵌入式linux的网络编程(1)--TCP/IP协议概述 1.OSI参考模型及TCP/IP参考模型 通信协议用于协调不同网络设备之间的信息交换,它们建立了设备之间互相识别的信息机制.大家一定都听说过著 ...

  6. Linux C网络编程学习笔记

    Linux C网络编程总结报告 一.Linux C 网络编程知识介绍: 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端:(client) 在网络程序中, ...

  7. Linux C++ 网络编程学习系列(1)——端口复用实现

    Linux C++ 网络编程学习系列(1)--端口复用实现 源码地址:https://github.com/whuwzp/linuxc/tree/master/portreuse 源码说明: serv ...

  8. Linux&C网络编程————“聊天室”

    从上周到现在一直在完成最后的项目,自己的聊天室,所以博客就没怎么跟了,今天晚上自己的聊天室基本实现,让学长检查了,也有好些bug,自己还算满意,主要实现的功能有: 登录注册 附近的人(服务器端全部在线 ...

  9. Linux&C网络编程————“聊天室”

    从上周到现在一直在完成最后的项目,自己的聊天室,所以博客就没怎么跟了,今天晚上自己的聊天室基本实现,让学长检查了,也有好些bug,自己还算满意,主要实现的功能有: 登录注册 附近的人(服务器端全部在线 ...

随机推荐

  1. jboss 配置虚拟路径

    1.找到jboss服务器下server.xml文件.我用的是web用户,所以在web用户下找 路径:G:\skWorkspace\Jboss\server\web\deploy\jbossweb.sa ...

  2. PHP实现写LOG日志的代码

    这篇文章给大家介绍的内容是关于PHP实现写LOG日志的代码,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. public function write_log(){ //设置目录时间 ...

  3. 自定义 Java Annotation ,读取注解值

    1. 首先是自定义注解: package cn.veji.hibernate.po; import java.lang.annotation.ElementType; import java.lang ...

  4. CMU-准备

    TOEFL成绩90分以上,GPA大于3.0,GRE1250分以上(不做明确要求) 申请条件:GRE成绩,建议有专科成绩;托福250,雅思7.0;简历;3封推荐信 TOEFL(The Test of E ...

  5. idea安装及使用

    使用:https://blog.csdn.net/qq_42303709/article/details/81983208 安装教程:https://blog.csdn.net/yl171272518 ...

  6. POJ2454——Jersey Politics

    POJ2454——Jersey Politics 题目大意: 在泽西奶牛和荷斯坦奶牛的最新普查中,威斯康星奶牛在谷仓中获得了三个档位. 泽西奶牛目前控制着国家重新分配委员会. 他们想将国家分为三个相当 ...

  7. 洛谷——P1176 路径计数2

    P1176 路径计数2 题目描述 一个N \times NN×N的网格,你一开始在(1,1)(1,1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N,N)(N,N),即右下角有 ...

  8. python环境配置以及基本知识

    python---一种解释型语言(脚本语言),具有代码简洁.入门简单.开发效率高的优点.当然不可避免的有着暴露源码.执行效率低的缺点,但毕竟瑕不掩瑜,在数据是无比宝贵的财富的当下,无疑是一门优秀的编成 ...

  9. buf.writeInt8()函数详解

    buf.writeInt8(value, offset[, noAssert]) value {Number} 需要被写入到 Buffer 的字节 offset {Number} 0 <= of ...

  10. Python运算符(Python学习笔记03)