Linux C 基于tcp多线程在线聊天室

多线程在线聊天室

  • 概述
  • 客户端
  • 服务端

概述

  客户端实现了判单用户登录结果、防止单回车字符发送、保存和显示历史聊天记录(仅自己)、退出聊天室功能。
  服务端实现了验证用户是否已经存在(支持最大64用户连接)支持广播用户进入退出聊天室以及用户聊天内容。

客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>typedef struct sockaddr  SA;
typedef struct sockaddr_in  SIN;
#define MAXBACKLOG   100
int Socket(int domain,int type,int protocol);
int Connect(int sockfd,struct sockaddr * serv_addr,int addrlen);
void *son_fun(void * arg);
void save(const char * dbuff,const char * nbuff);
void list_history_msg(const char * nbuff);
int main(int argc,char *argv[])
{	char namebuff[512]={0};pthread_t id;//建立监听套接字int socketfd = Socket(AF_INET,SOCK_STREAM,0);//connectSIN   serverinfo;serverinfo.sin_family = AF_INET;serverinfo.sin_port   = htons(atoi(argv[2]));serverinfo.sin_addr.s_addr =  inet_addr(argv[1]);int addrlen = sizeof(SIN);Connect(socketfd,(SA*)&serverinfo,addrlen);//send nameprintf("请输入昵称:\n");gets(namebuff);write(socketfd,namebuff,sizeof(namebuff));char b[20];read(socketfd,b,sizeof(b));if(strstr(b,"已存在")){printf("已存在\n");close(socketfd);return 0;		}//print serve infoprintf("登入成功,服务器:%s 端口:%d\n",inet_ntoa(serverinfo.sin_addr),ntohs(serverinfo.sin_port));//make son threadpthread_create(&id,NULL,son_fun,(void *)&socketfd);//w while(1){//timetime_t t = time(NULL);struct tm *tinfo = localtime(&t);//msgchar readbuff[512] = {0};gets(readbuff);//prevent "\n" send to serve and save to dataif(strlen(readbuff)==0) continue;//determine wheather it is "ls"if(strcmp(readbuff,"ls") == 0) {list_history_msg(namebuff);continue;}//determine wheather it is "quit"if(strcmp(readbuff,"quit") == 0){char sendbuff[618] = {0};sprintf(sendbuff,"%s : %s%s",namebuff,asctime(tinfo),"退出聊天");write(socketfd,sendbuff,sizeof(sendbuff));close(socketfd);exit(0);}//sendchar sendbuff[618] = {0};sprintf(sendbuff,"%s : %s%s",namebuff,asctime(tinfo),readbuff);write(socketfd,sendbuff,sizeof(sendbuff));//save datasave(sendbuff,namebuff);}//关闭close(socketfd);return 0;
}
void list_history_msg(const char * nbuff)
{char path[128];char *line = NULL;size_t len = 0;sprintf(path,"./userdata/%s.txt",nbuff);FILE * fp = fopen(path,"a+");printf("********聊天记录*********\n");while(getline(&line , &len , fp) != -1)printf("%s",line);printf("************************\n");free(line);fclose(fp);
}
void save(const char * dbuff,const char * nbuff)
{char path[128];sprintf(path,"./userdata/%s.txt",nbuff);FILE * fp = fopen(path,"a+");fprintf(fp,"%s\n",dbuff);fclose(fp);
}int Socket(int domain,int type,int protocol)
{int socketFd = socket(domain,type,protocol);if(socketFd == -1){perror("socket");exit(1);}return socketFd;
}
int Connect (int sockfd,struct sockaddr * serv_addr,int addrlen)
{int val = connect(sockfd,serv_addr,addrlen);if(val == -1){perror("connect");exit(1);}return 0;
}
void *son_fun(void * arg)
{int readpipefd = *((int *)arg);char readbuff[512]={0};while(1){memset(readbuff,0,sizeof(readbuff));if(read(readpipefd,readbuff,sizeof(readbuff))>0){printf("%s\n\n",readbuff);}else{close(readpipefd);pthread_exit(NULL);}}
}

服务端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <semaphore.h>typedef struct sockaddr  SA;
typedef struct sockaddr_in  SIN;
#define MAXBACKLOG   100int Socket(int domain,int type,int protocol);
int Bind(int sockfd,struct sockaddr * my_addr,int addrlen);
int Listen(int s,int backlog);
int Accept(int s,struct sockaddr * addr,int * addrlen);
void *son_fun(void * arg);
int is_exist(char * username);
void broadcast(char *r,char *n);char Userlist[64][20] = {0};
int Userfdlist[64] = {0};int main(int argc,char *argv[])
{	//建立监听套接字int socketfd = Socket(AF_INET,SOCK_STREAM,0);//需要进行重用地址及其端口号int  opt = 1;setsockopt(socketfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));//绑定信息编写服务器信息SIN   serverinfo;serverinfo.sin_family = AF_INET;		//协议IPV4serverinfo.sin_port   = htons(atoi(argv[2]));	//网络字节序(大端字节序)与主机字节序(小端字节序)  serverinfo.sin_addr.s_addr =  inet_addr(argv[1]);int addrlen = sizeof(SIN);Bind(socketfd,(SA*)&serverinfo,addrlen);//监听Listen(socketfd,MAXBACKLOG);//读写while(1){//等待连接SIN clientinfo;int  clientaddrlen = sizeof(SA);int newfd = Accept(socketfd,(SA*)&clientinfo,&clientaddrlen);printf("客户端地址:%s 端口号:%d\n",inet_ntoa(clientinfo.sin_addr),ntohs(clientinfo.sin_port));//创建子线程pthread_t id;pthread_create(&id,NULL,son_fun,(void *)&newfd);}//关闭close(socketfd);return 0;
}
int is_exist(char * username)
{for(int i = 0 ; i < 10; i++){if(strcmp(username,Userlist[i]) == 0)return 1;}return 0;
}
void *son_fun(void * arg)
{int readfd = *((int *)arg);char readbuff[512] = {0};char namebuff[ 20] = {0};read(readfd,namebuff,sizeof(namebuff));//determine wherther it is existif(is_exist(namebuff)){write(readfd,"已存在",sizeof("已存在"));close(readfd);pthread_exit(NULL);}else{write(readfd,"登录成功",sizeof("登录成功"));char r[50];sprintf(r,"%s %s",namebuff,"进入聊天室");printf("%s\n",r);broadcast(r,namebuff);}//save username and userfdfor(int i=0;i<10;i++){if(strlen(Userlist[i])==0){strcpy(Userlist[i],namebuff);Userfdlist[i] = readfd;break;}}while(1){memset(readbuff,0,sizeof(readbuff));if(read(readfd,readbuff,sizeof(readbuff))>0){if(strlen(readbuff)>0){//printf("%s\n\n",readbuff);//broadcastbroadcast(readbuff,namebuff);if(strstr(readbuff,"退出聊天"))for(int i=0;i<10;i++)if(strcmp(Userlist[i],namebuff)==0){printf("%s\n",readbuff);strcpy(Userlist[i],"\0");close(readfd);pthread_exit(NULL);}}}else{close(readfd);pthread_exit(NULL);}}
}
void broadcast(char *r,char *n)
{for(int i=0 ; i<10 ;i++)//if it is a user and not himselfif(strcmp(Userlist[i],n)!=0 && strlen(Userlist[i])!=0)write(Userfdlist[i],r,strlen(r));
}
int Socket(int domain,int type,int protocol)
{int socketFd = socket(domain,type,protocol);if(socketFd ==-1){perror("socket");exit(1);}return socketFd;
}
int Bind(int sockfd,struct sockaddr * my_addr,int addrlen)
{int val = bind(sockfd,my_addr,addrlen);if(val){perror("bind");exit(1);}return 0;
}
int Listen(int s,int backlog)
{int val = listen(s,backlog);if(val == -1){perror("listen");exit(1);}return val;
}
int Accept(int s,struct sockaddr * addr,int * addrlen)
{int NEWfd = accept(s,addr,addrlen);if(NEWfd == -1){perror("listen");exit(1);}return NEWfd;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/154363.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自定义类型转换函数operator MyInt()

/*** * 结论&#xff1a;对pass-by-value传参的常规调用&#xff0c;会用实参拷贝构造形参&#xff0c;实参与形参相互无影响&#xff1b; * 当对实参调用类型转换函数(返回形参类型)&#xff0c;编译器会优化代码使类型转换函数返回值直接构造在调用作用域的接受对象上 */ …

AR眼镜方案—单目光波导AR智能眼镜

光波导技术是一项具有前沿意义的技术&#xff0c;它能够将光线反射180度&#xff0c;使得眼镜框架内置的MicroLED屏幕的图像通过多次反射与扩散后准确地传递到人眼中。采用MicroLED显示技术的AR智能眼镜不仅体积显著缩小&#xff0c;屏幕只有0.68英寸大小&#xff0c;并且还能够…

crontab

crontab 详细用法 定时任务_crontab每周六凌晨一点重启-CSDN博客 使用 Crontab 设置开机启动 Python 脚本_crontab开机启动脚本-CSDN博客 编写一个 shell 脚本 $ cat test.sh #!/bin/bashpython3 main.py > ~/output-20230901.txtubuntu环境下开启定时任务crontab_ubuntu…

华为HCIE技术(HCIP、HCIE)汇总

我所在的岗位是网络运维&#xff0c;路由与交换用的比较多&#xff0c;外网技术比较少。所以把经常用的写的比较详细。大家多多包涵。 理论部分 网络基础&#xff1a;ISO网络七层模型 交换机部分 首次Console口登陆配置Telnet访问 VLAN VLAN的介绍、单交换机vlan划分实验…

KT142C语音芯片音乐前要空白音才行,声音会被截掉,实际语音是你好,播放变成好

KT142C语音芯片播放音乐前必须有一段空白音才行&#xff0c;不然声音会被截掉一部分&#xff0c;播放 温度1超高&#xff0c;如果前面没有空白音&#xff0c;就会变成 度1超高 出现这个问题&#xff0c;核心的原理在于功放芯片是受控了 这个问题只存在于&#xff0c;配置为DAC…

软考必须得从初级开始考吗?

软考是指软件技术专业资格考试&#xff0c;是由中国计算机技术职业资格认证中心&#xff08;NCTC&#xff09;主办的一项国家级考试。软考考试内容涵盖了软件工程、数据库、网络与信息安全、嵌入式系统等多个方面的知识&#xff0c;是评价软件技术人员专业水平的重要标准。 对于…

手机 IOS 软件 IPA 签名下载安装详情图文教程

由于某些应用由于某些原因无法上架到 appStore 或者经过修改过的软件游戏等无法通过 appStore 安装&#xff0c;我们就可以使用签名的方式对相应软件的IPA文件进行签名然后安装到你的手机上 这里我们使用爱思助手进行签名安装&#xff0c;爱思助手支持两种方式&#xff0c;一种…

visionOS空间计算实战开发教程Day 1:环境安装和编写第一个程序

安装 截至目前visionOS还未在Xcode稳定版中开放&#xff0c;所以需要下载​​Xcode Beta版​​。比如我们可以下载Xcode 15.1 beta 2&#xff0c;注意Xcode 15要求系统的版本是macOS Ventura 13.5或更新&#xff0c;也就是说2017年的MacBook Pro基本可以勉强一战&#xff0c;基…

从复杂大模型加载到3D PDF发布: EVGET HOOPS Framework如何助力高性能3D桌面应用开发?

在当今数字化时代&#xff0c;3D图形和CAD&#xff08;计算机辅助设计&#xff09;技术在各行各业中扮演着至关重要的角色。 HOOPS SDK是由Tech Soft 3D公司开发的一套强大的3D图形和CAD&#xff08;计算机辅助设计&#xff09;开发工具包。HOOPS致力于提供先进的3D复杂数据处…

艾泊宇产品战略:探索产品战略对品牌价值的重要性

一、流量型广告与认知型广告 大家都知道&#xff0c;在如今的商业环境中&#xff0c;媒体广告主要分为两种&#xff1a;流量型广告和认知型广告。 流量型广告&#xff0c;咱们就把它叫做“伟哥模式” 伟哥你懂的&#xff0c;吃一颗立马见效&#xff0c;效果非凡。但问题是&a…

Codesys扩展数据类型Any的探索

Codesys代码代写&#xff0c;程序开发&#xff0c;软件定制&#xff0c;bug修改&#xff0c;问题咨询&#xff1a; TAO宝搜索店铺【林磊教育】 ANY 定义 Any内部是一个数据结构体&#xff0c;在定义一个Any变量时&#xff0c;内部会转成其结构体&#xff0c;定义如下 TYPE An…

数据结构与算法之美学习笔记:23 | 二叉树基础(上):什么样的二叉树适合用数组来存储?

目录 前言树&#xff08;Tree&#xff09;二叉树&#xff08;Binary Tree&#xff09;二叉树的遍历解答开篇 & 内容小结 前言 本节课程思维导图&#xff1a; 前面我们讲的都是线性表结构&#xff0c;栈、队列、链表等等。今天我们讲一种非线性表结构&#xff0c;树。问题&…

WebGoat通关攻略之 SQL Injection (intro)

SQL Injection (intro) 1. What is SQL? 本题练习SQL查询语句&#xff0c;就是写一句SQL获取叫Bob Franco所在的department SELECT department FROM employees WHERE first_name Bob AND last_name Franco成功通关&#xff01; 2. Data Manipulation Language (DML) 本题…

安卓毕业设计:基于安卓android微信小程序的超市购物系统

运行环境 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&a…

喜报 | 思码逸 DevInsight 通过DaoCloud兼容性互认证

近日&#xff0c;北京思码逸科技有限公司&#xff08;简称&#xff1a;思码逸&#xff09;的 Devlnsight 一站式研发效能度量平台与上海道客网络科技有限公司&#xff08;简称&#xff1a;DaoCloud&#xff09;的 DaoCloud Enterprise 云原生操作系统 V5.0&#xff0c;经双方联…

数据结构:lambda表达式

基本概念 语法 // 1. 不需要参数,返回值为 2 () -> 2 // 2. 接收一个参数(数字类型),返回其2倍的值 x -> 2 * x // 3. 接受2个参数(数字),并返回他们的和 (x, y) -> x y // 4. 接收2个int型整数,返回他们的乘积 (int x, int y) -> x * y // 5. 接受一个 string 对…

配置中心

服务配置中心介绍 首先我们来看一下,微服务架构下关于配置文件的一些问题&#xff1a; 1. 配置文件相对分散。 在一个微服务架构下&#xff0c;配置文件会随着微服务的增多变的越来越多&#xff0c;而且分散 在各个微服务中&#xff0c;不好统一配置和管理。 2. 配置文件无…

ACREL DC energy meter Application in Indonesia

安科瑞 华楠 Abstract: This article introduces the application of Acrel DC meters in base station in Indonesia.The device is measuring current,voltage and energy together with hall current sensor. 1.Project Overview This company is located in Indonesia a…

APP分发平台指的是将开发完成的应用程序

APP分发平台指的是将开发完成的应用程序推广和发布到用户可以下载和安装的渠道&#xff0c;如应用商店、第三方分发平台等&#xff0c;以让更多的用户知道和使用该应用程序&#xff0c;从而提升应用的用户覆盖率和市场份额。在APP分发过程中&#xff0c;需要对APP分发进行一系列…

Java WebSocket 获取客户端 IP 地址

在开发 Web 应用程序时&#xff0c;我们通常需要获取客户端的 IP 地址用于日志记录、身份验证、限制访问等操作。当使用 WebSocket 协议时&#xff0c;我们可以使用 Java WebSocket API 来获取客户端的 IP 地址。 本文将介绍如何使用 Java WebSocket API 获取客户端 IP 地址&a…