由于使用了多线程操作,客户端进入程序后请先随便注册一次用户后再进行使用。

本程序默认第一个用户即ID为1的用户为超级管理员。

由于线程阻塞,最后的踢人操作有阻塞,需要在被踢出在线链表后手动下线。

看了老师给的颜色控制命令之后,再也不想print白色的字了。。。

聊天室项目编写时遇到的问题:

首先一定要备份,完成一步备份一下!

1.最开始卡住是那天的strncpy,查错查了一下午加一个晚上,最后鹏哥帮着一个个print才发现是这个函数的问题。能用strcpy的地方一定不要用strncpy!
2.然后就是返回值来决定菜单的显示,这个问题困扰了一天半,然后把程序拷贝到redhat上就可以跑了???回到Ubuntu一个个print,线程跑的比较慢,所以read的值能不能传过来,要看主进程跑的比线程慢还是快了,最后一个sleep解决了一切卡了一天半的问题。没事就要sleep!
3.然后链表卡住了,这块知识掌握的的不够牢固,最后一天在宿舍从起床到吃完饭一直在看链表,在梅总的指导下总算是对链表有了个清晰的认识,链表卡了一天!
4.传参的细节问题,*星号,  取地址符一定要会用。传参到底是形参还是实参一定要搞懂!
5.最后虽然完成了程序但是由于框架是用if else搭出来的,显得比switch case框架笨重很多,而且最后的管理员踢人功能也没法完美的实现跳出菜单。做东西前,一定要先有规划,规划好框架再写,要么最后改都改不了!

一、基本内容和要求

基本内容:

本课程设计主要实现一个Linux下的局域网聊天工具的设计。该设计主要分为两部分,客户端部分和主机部分。运行服务器端程序可以和任意运行了客户端程序的主机进行通信,通信内容能够通过终端显示出来。两个部分都使用C语言,利用vim编辑器,通过Berkeley套接口编程实现相关功能。

基本要求:

设计一个可以运行在Linux平台下C/S架构的即时聊天系统,实现聊天的各种基本功能。

二、项目配置

A.  功能:能够正确注册,登录,退出;

能够查询、添加、删除好友;

能够查看好友资料信息和状态信息;

能够实现个人资料信息维护、修改、更新个人状态信息;

能能在显示好友列表时显示好友状态;

能够实现正常地发送接收消息

能够查看聊天记录.

能够实现管理员功能;

能够实现文件传输;

B.  性能: 准确即时发送数据到指定用户;

能承载一定用户数量压力的服务器;

C.  输出:注册信息,存储到数据库中;

个人信息表,存到相应的个人用户下;

个人状态表,存储个人ID、是否在线等;

好友列表,查看好友的信息、状态、ID等;

D.  输入:输入ID登录,查找ID、添加好友ID;

修改个人信息、个人状态;

发送聊天信息,查看聊天记录;

E.  安全方面:IP与ID一一对应,ID与密码匹配登录

F.  支持系统:Linux;

三、Linux-C相关知识

3.1 socket编程头文件和常用函数

【IP地址转换函数】

点分十进制   整数  inet_pton和inet_ntop这2个函数能够处理ipv4和ipv6。算是比较新的函数了。

{

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>      // arpa/inet.h:提供IP地址转换函数

}

sys/types.h:数据类型定义

sys/socket.h:提供socket函数及数据结构

netinet/in.h:定义数据结构sockaddr_in

arpa/inet.h:提供IP地址转换函数

netdb.h:提供设置及获取域名的函数

sys/ioctl.h:提供对I/O控制的函数

sys/poll.h:提供socket等待测试机制的函数

其他在网络程序中常见的头文件

unistd.h:提供通用的文件、目录、程序及进程操作的函数

errno.h:提供错误号errno的定义,用于错误处理

fcntl.h:提供对文件控制的函数

time.h:提供有关时间的函数

crypt.h:提供使用DES加密算法的加密函数

pwd.h:提供对/etc/passwd文件访问的函数

shadow.h:提供对/etc/shadow文件访问的函数

pthread.h:提供多线程操作的函数

signal.h:提供对信号操作的函数

sys/wait.h、sys/ipc.h、sys/shm.h:提供进程等待、进程间通讯(IPC)及共享内存的函数

建议:在编写网络程序时,可以直接使用下面头文件代码

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netdb.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>

#include <errno.h>

#include <malloc.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <sys/ioctl.h>

#include <stdarg.h>

#include <fcntl.h>

#include <fcntl.h>

涉及到用户权限及密码验证问题时加入如下语句:

#include <shadow.h>

#include <crypt.h>

#include <pwd.h>

需要注意的是,应该在编译时链接加密算法库,即增加编译选项:

-lcrypt

涉及到文件及时间操作加入如下语句:

#include <sys/time.h> #include <utime.h> #include <time.h>

#include <sys/stat.h> #include <sys/file.h>

涉及到多进程操作时加入如下语句:

#include <sys/wait.h> #include <sys/ipc.h>

#include <sys/shm.h> #include <signal.h>

涉及到多线程操作时加入如下语句:

#include <pthread.h> #include <sys/poll.h>

需要注意的是,应该在编译时链接线程库,即增加编译选项:

-lthread

绑定端口

int bind(int sockfd, struct sockaddr *sa, int addrlen);

连接网络(TCP)

int connect(int sockfd, struct sockaddr *servaddr, int addrlen);

监听端口(TCP)

int listen(int sockfd, int queue_length);

响应连接请求(TCP)

int accept(int sockfd, struct sockaddr *addr, int *addrlen);

关闭

int close(int sockfd);

int shutdown(int sockfd, int how);

0—-禁接收

1—禁发送

2—禁收发

轮询

int select(int numfds, fd_set *readfds, fd_set * writefds,  fd_set * exceptfds, struct timeval* timeout);

注意windows和unix中,函数返回后fd_set内容发生了改变,下次使用必须重新赋值。

接收和发送:

TCP: int send(int s, const void* buf, int len, int flags);

int recv(….);

UDP: int sendto(int s, const void* buf, int len, int flags, const struct sockaddr* to, int tolen);

int recvfrom(…);

基于消息的方式:

int sendmsg(int s, const struct msghdr * msg, int flags);

int recvmsg(…);

3.2 Linux文件编程

1.Linux系统调用

操作系统负责管理和分配所有的计算机资源,为了更好的服务于应用程序,操作系统提供了一组特殊接口------系统调用。

通过这组接口用户程序可以使用操作系统内核提供的各种功能,主要包括:进程控制、进程通信、文件系统管理、内存管理、I/O管理、网络管理、套接字等

问题:为什么不允许程序直接访问计算机资源???

2.用户编程接口API

用户编程接口API俗称库函数,为了提高用户的编程效率,开发环境会把实现特定功能的函数封装成函数库供用户调用。

系统调用/用户编程接口API

一个是系统级别,一个是用户级别

系统调用提供的数量和功能有限,函数库非常丰富

系统调用属于操作系统内核功能,移植性受限,用户编程接口API与内核无关,只要计算机上安装了相应函数库,就可以调用,移植性好。

3.POSIX规范

Portable Operation System Interface

可移植的操作系统接口规范,由IEEE制定,目的是为了提高UNIX环境下的应用程序可移植性。

Linux类UNIX操作系统

4.Linux文件I/O

Linux下一切皆文件:

6类:普通文件、目录文件、符号链接文件、管道文件、套接字文件、设备文件

l文件描述符:

对于内核而言,所有打开文件都由文件描述符表示。

文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。

当读、写一个文件时,用open或creat返回的文件描述符标识该文件,将其作为参数传送给read或write。

5.文件标准I/O

ANSI C定义的用于I/O操作的一系列API函数

文件指针

FILE:每个被打开的文件都在内存中开辟一个区域,用来存放文件的有关信息。这些信息保存在一个结构体类型的变量中,该结构体类型是由系统定义的,称为FILE(流)。

标准I/O库的所有操作都是围绕流(stream)来进行的,在标准I/O中,流用FILE 来描述。

流的含义:

定义:所有的I/O操作本质上都是从文件中输入或输出字节流,所以称为流。

分类:文本流/二进制流。

文本流

定义:在流中处理的数据是以字符出现。在文本流中,’\n’被转换成回车                 符CR和换行符LF的ASCII码0DH和0AH。而当输出时,0DH和0AH                   被转换成’\n’

数字2001在文本流中的表示方法为  ‘2’  ‘0’  ‘0’  ‘1’                                                   ASCII:    50  48  48  49

ASCII:   32  30   30  31

ASCII    0010 0000  0001 1110  0001 1110  0001 1111

二进制流

定义:流中处理的是二进制序列。若流中有字符,则用一个字节的二进制                 ASCII码表示;若是数字,则用对应的二进制数表示。对’\n’不进行                 变换

数字2001在二进制流中的表示方法为 00000111  11010001。

缓冲:

目的:尽量减少使用read/write的调用

定义:系统自动的在内存中为每一个正在使用的文件开辟一个缓冲区,从内存向磁盘输出数据必须先送到内存缓冲区,装满缓冲区在一起送到磁盘中去。从磁盘中读数据,则一次从磁盘文件将一批数据读入到内存缓冲区中,然后再从缓冲区逐个的将数据送到程序的数据区。

全缓冲

当填满I/O缓存后才进行实际I/O操作,或者满足一定条件后,系统通过调用malloc来获得所需要的缓冲区域,默认值全缓冲。

刷新(fflush):标准I/O的写操作。

当缓冲区满了,或者满足一定的条件后,就会执行刷新操作。

行缓冲

当在输入和输出中遇到新行符(‘\n’)时,进行I/O操作。

当流遇到一个终端时,典型的行缓存。

无缓冲

标准错误流stderr无缓冲。

很多的人机交互界面要求不可全缓冲。

标准I/O预定义3个流,他们可以自动地为进程所使用

标准输入

0

STDIN_FILENO

stdin

标准输出

1

STDOUT_FILENO

stdout

标准错误输出

2

STDERR_FILENO

stderr

6.文件I/O与标准I/O的区别

l文件I/O又称为低级磁盘I/O,遵循POSIX标准,在支持POSIX标准的系统上都能运行。

l标准I/O称为高级磁盘I/O,遵循ANSI C标准,只要系统中有标准C函数库,就可以运行。

l文件I/O执行读写操作时,会执行系统调用,直接读写磁盘文件。缺点:频繁执行系统调用增加了系统开销,因为频繁在用户态与内核态进行切换。

l标准I/O是在文件I/O的基础上封装了缓冲机制,所有文件操作实际上是在缓冲区里进行的,必要时才实际读写磁盘文件。缺点:如果程序异常退出,缓冲区里的内容有可能没有写入磁盘文件,信息丢失。

l文件I/O可以操作任何类型的文件

l标准I/O只能读写普通文件

7.文件I/O操作

l不带缓冲

l通过文件描述符来访问文件

文件I/O常用函数

open()/creat() close() read() write() lseek()

8.标准I/O操作

fopen() fclose()

fgetc()/fputc()一次读或写一个字符。

fgets()和fputs()一次读或写一行。

fread()和fwrite()函数支持直接I/O

fseek() ftell() rewind() Fflush()

3.3 线性表的顺序存储结构

1.线性表的顺序存储结构

typedef int datatype;

typedef struct Sqlist {

datatype List[MAX];

int length;

}Sqlist;

Sqlist L;

注意:初始化length的赋值含义;插入、删除操作的位置判断、溢出判断;插入或者删除后数据元素向后或者向前移动范围判断;

2.线性表的链式存储结构

typedef int ElemType;

typedef struct Node

{

ElemType data;

struct Node *next;

}Node;

typedef struct Node * LinkList;

LinkList L;

函数原型:Initiate(LinkList *L)

函数调用:Initiate(&L);

*L=(LinkList)malloc(sizeof(Node));

注意:头节点概念(类型也是Node,不保存数据);

头指针概念(头节点的next指针的值,保存的第一个数据节点的地址);

插入、删除时的判断条件,注意判断条件的差异(插入p!=NULL   /   删除p->next!+NULL)

插入时,p指向要插入的位置i的前一个节点(1=<i<=Listlength()+1)

p = *L; j = 1;

while (p!=NULL && j < i)     /* 寻找第i个结点 */

{

p = p->next;

++j;

}

if (p==NULL || j > i)

return ERROR;   /* 第i个元素不存在 */

s = (LinkList)malloc(sizeof(Node));  /* 生成新结点 */

s->data = e;

s->next = p->next;      /* 将p的后继结点赋值给s的后继  */

p->next = s;          /* 将s赋值给p的后继 */

删除时,p指向要删除的位置i的前一个节点(1=<i<=Listlength())

p = *L; j = 1;

while (p->next!=NULL && j < i)  /* 遍历寻找第i个元素 */

{

p = p->next;

++j;

}

if ((p->next)==NULL || j > i)

return ERROR;           /* 第i个元素不存在 */

q = p->next;

p->next = q->next;  /* 将q的后继赋值给p的后继 */

free(q);

3.4多线程知识

线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者.传统的Unix也支持线程的概念,但是在一个进程(process)中只允许有一个线程,这样多线程就意味着多进程.现在,多线程技术已经被许多操作系统所支持,包括Windows/NT、Linux。

进程:进程是一个具有一定独立功能的程序的一次运行活动,同时也是资源分配的最小单元;进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集。从内核的观点看,进程的目的就是担当分配系统资源(CPU时间、内存等)的基本单位。

Linux系统是一个多进程的系统,它的进程之间具有并行性、互不干扰等特点。

也就是说,每个进程都是一个独立的运行单位,拥有各自的权利和责任。其中,各个进程都运行在独立的虚拟地址空间,因此,即使一个进程发生异常,它也不会影响到系统中的其他进程。

Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用libpthread.a。

四、源程序注解

见程序:https://download.csdn.net/download/qq_39540224/10548861

五、结果分析

运行环境ubuntu12.04

详见:Linux环境下——C语言聊天室项目界面展示

https://blog.csdn.net/qq_39540224/article/details/81098507

六、结论

本课程设计主要实现一个Linux下的局域网聊天工具的设计。该设计主要分为两部分,客户端部分和主机部分。运行服务器端程序可以和任意运行了客户端程序的主机进行通信,通信内容能够通过终端显示出来。两个部分都使用C语言,利用vim编辑器,通过Berkeley套接口编程实现相关功能。完成了一个可以运行在Linux平台下C/S架构的即时聊天系统,实现聊天的各种基本功能。

Linux环境下——C语言聊天室项目相关推荐

  1. 超详细:实现过程-Linux 环境下的简易聊天室,采用CS模型,实现多客户端之间的稳定数据传输。--注册和登录(但之后会连续更新内容,直至全部实现)

    前言 在学完不够全面的Linux操作系统编程后(这也意味着我后期也要不断学习,这也符合我活到老学到老的人生观点),需要以一些项目来检测自己的所学,毕竟实践见真章. 所以在今后的几天里,我将以无界面聊天 ...

  2. 2021.10.02超详细实现过程-Linux 环境下的简易聊天室,采用CS模型,实现多客户端之间的稳定数据传输。(添加好友,删除好友、屏蔽好友、查看好友列表(针对数据库的操作))

    这次主要对加好友.删除好友.屏蔽好友.查看好友列表功能(单纯的基于数据库操作),并且也对之前的代码做了部分的改动,为中间涉及全局变量问题. 对之前的改动(主要): 其中对结构体进行了改动和结构体全局变 ...

  3. c语言Linux用线程创建文件,Linux环境下C语言线程创建---简单代码

    在Linux环境下用C语言编写线程创建. //file name: pthreadtext.c #include #include //线程头文件 //pthread不是linux下的默认的库,也就是 ...

  4. linux环境下c语言的学习--linux下的基本操作

    linux环境下c语言学习 星期一 _代表空格 1.在linux下打开一个终端:ctrl+alt+t       多次使用可打开多个终端. 2.创建一个文件夹:mkdir_ abc           ...

  5. linux贪吃蛇c程序,Linux环境下C语言实现贪吃蛇游戏

    Linux环境下C语言实现贪吃蛇游戏 [liul@test snake]$ more snake.c #include #include #include #include #include #def ...

  6. 南工程c语言实验报告,Linux环境下-C语言编程实验报告(1)(总4页).doc

    Linux环境下-C语言编程实验报告(1)(总4页).doc 西 安 邮 电 大 学 (计算机学院)课内实验报告实验名称 Linux环境下 C语言编程 专业名称 网络工程班 级 1203班 学生姓名 ...

  7. linux环境c语言课程设计,linux环境下c语言编程课程设计

    linux环境下c语言编程课程设计 (14页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 1/14LINUX操作系统教程课程设计题目算术 ...

  8. C语言聊天室项目说明书

    网络聊天室项目说明 项目的目的和意义 该聊天室项目为利用linux下C语言网络编程相关知识,采用Server/Client,即服务器与客户端的基本框架实现.整个项目涉及了socket套接字,线程,嵌入 ...

  9. linux下c语言聊天室程序,纯C语言Socket实现聊天室

    最近在学习嵌入式开发,练习C语言小项目,基本是参考别人的代码,做了些修改实现了聊天室,纯C语言编写. 想直接看源码的跳到最后. 一.练习内容 socket通信流程 管道的使用 epoll的使用 首先要 ...

最新文章

  1. java抽象工厂模式_Java 抽象工厂模式
  2. 直接排序python实现
  3. pythontkinter控件单选框怎么判断是否被选中_Python GUI编程(Tkinter)Radiobutton单选框控件...
  4. C语言实现类似QQ聊天界面抖动功能
  5. 学习响应式BootStrap来写融职教育网站,Bootsrtap第五天页脚
  6. 守护线程Daemon的理解
  7. leetcode25. K 个一组翻转链表
  8. NodeJS知识汇总
  9. udp模拟tcp java_Java简单实现UDP和TCP
  10. Good Time 冲刺 六
  11. Flutter 微信分享功能实现
  12. 不插网线 开机速度加快
  13. 通俗易懂的Monte Carlo积分方法(二)
  14. 微信AES-128-CBC加密解密
  15. PHP之JWT接口鉴权(二) 自定义错误异常
  16. Split()函数的作用
  17. Mac将Wps本地文件备份到云端
  18. Word另存为PDF后无导航栏解决办法
  19. 喜欢游戏学计算机,我喜欢电脑游戏小学作文
  20. vue 2 组件之间传值

热门文章

  1. 怎么重置imac_[重置系统]如何重置Mac电脑到出厂状态
  2. VUX--小白初学使用安装
  3. 垃圾收集器和内存分配策略
  4. Spring注解驱动
  5. 【ESP32 S3开发】在Arduino IDE中使用PSRAM
  6. ASP.NET MVC5+EF6+EasyUI 后台管理系统(53)-工作流设计-我的批阅
  7. 网易互娱2017实习生招聘在线笔试(一)
  8. 什么是模块化代码?如何写?
  9. 某商场TD-LTE室内覆盖规划
  10. Cocoa -- 添加和移除开机启动项