基于Linux下TCP/IP协议局域网聊天室
这几天一直在看TCP/IP这块的内容,写个简单socket通信demo,实现了多个客户端相互发送消息,以及服务端给多个客户端发送上线/下线消息
基本框架:
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>#define PORT 6666
#define NUM_MAX_WAIT 1
#define NUM_MAX_CHAT 2typedef struct Message {bool type; // 0: system 1: clientchar buff[1024];char name[30];
}Message;typedef struct Client {bool c_flage;int c_fd;
}Client;int sockfd = 0;
int num_chat = 0;
bool quit = false;
pthread_t ptid[2] = {};
Client client[4] = {};void* pthread_comm(void* argc)
{Client* cli_com = argc;Message msg = {};int ret = recv(cli_com->c_fd, &msg, sizeof(msg), 0); if(0 == strlen(msg.buff) && 0 < strlen(msg.name)) {//printf("name:%s fd:%d flage:%d num_chat:%d\n", name_tmp, cli_com->c_fd, cli_com->c_flage, num_chat);bzero(&msg.buff, sizeof(msg.buff));msg.type = 0;sprintf(msg.buff, "==========[%s] 已进入聊天室[%d人] ==========", msg.name, num_chat);for(int i=0; i< NUM_MAX_CHAT; i++) {if(client[i].c_flage == true)send(client[i].c_fd, &msg, sizeof(msg), 0); }}while(1) {bzero(&msg, sizeof(msg));int ret = recv(cli_com->c_fd, &msg, sizeof(msg), 0); if(ret > 0 ) { if((strcmp("quit", msg.buff)) == 0) {num_chat--;cli_com->c_flage = false;msg.type = 0;//printf("name:%s fd:%d flage:%d num_chat:%d\n", msg.name, cli_com->c_fd, cli_com->c_flage, num_chat);sprintf(msg.buff, "==========[%s] 已退出聊天室[%d人] ==========", msg.name, num_chat);for(int i=0; i< NUM_MAX_CHAT; i++) {if(client[i].c_flage == true)send(client[i].c_fd, &msg, sizeof(msg), 0); }bzero(&msg, sizeof(msg));break;}else {//printf("recver:%s by %s\n", msg.buff, msg.name);msg.type = 1;for(int i=0; i<NUM_MAX_CHAT; i++) {if(client[i].c_flage == true)send(client[i].c_fd, &msg, sizeof(msg), 0);}}}}pthread_exit(NULL);
}void* pthread_accept(void *argc)
{struct sockaddr_in client_sk;socklen_t client_len = sizeof(struct sockaddr_in);bzero(&client_sk, sizeof(client_sk));printf("========== 聊天室已创建 ==========\n");while(1) {if(NUM_MAX_CHAT > num_chat) {int i ;for(i=0; i< NUM_MAX_CHAT; i++) {if(client[i].c_flage == false) {client[i].c_fd = accept(sockfd, (struct sockaddr*)&client_sk, &client_len);client[i].c_flage = true; printf("client[%d] fd:%d flage:%d chat_num:%d\n", i, client[i].c_fd, client[i].c_flage, num_chat);break;}}num_chat++;if((pthread_create(&ptid[1], NULL, pthread_comm, &client[i])) !=0 ){perror("pthread comm create");pthread_exit(NULL);}}}pthread_exit(NULL);
}int main(char argc, char *argv)
{struct sockaddr_in serv_sk;if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {perror("Create socket");exit(1);}bzero(&serv_sk, sizeof(serv_sk));serv_sk.sin_family = AF_INET;serv_sk.sin_port = htons(PORT); serv_sk.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(sockfd, (struct sockaddr *)&serv_sk, sizeof(serv_sk)) == -1) {perror("Bind socke");exit(1);}listen(sockfd, NUM_MAX_WAIT);if(pthread_create(&ptid[0], NULL, pthread_accept, NULL) != 0) {perror("pthread accept create");pthread_exit(NULL);} while(!quit);close(sockfd);
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sys/socket.h>
#include <string.h>#define PORT 6666
#define MAX_BUFF 1024typedef struct Message {bool type; //0: system 1:clientchar buff[MAX_BUFF];char name[30];
}Message;Message send_msg = {};
Message recv_msg = {};
int sockfd = 0;
bool quit = false;void* pthread_recv(void* argc)
{while(1) {bzero(&recv_msg.buff, sizeof(recv_msg.buff));int ret = recv(sockfd, &recv_msg, sizeof(recv_msg), 0);if(0 < strlen(recv_msg.buff)) {if(recv_msg.type)printf("%s: %s\n", recv_msg.name, recv_msg.buff);elseprintf("%s\n", recv_msg.buff);}}close(sockfd);
}void* pthread_send(void* argc)
{send_msg.type = 0;send(sockfd, &send_msg, sizeof(send_msg), 0);while(1) {bzero(&send_msg.buff, sizeof(send_msg.buff));send_msg.type = 1;gets(send_msg.buff);printf("\33[1A");printf("\r \r");if(0 < strlen(send_msg.buff)) {//printf("%s send:%s\n", send_msg.name, send_msg.buff);send(sockfd, &send_msg, sizeof(send_msg), 0);if(!strcmp("quit", send_msg.buff)) {quit = true;break;}}}
}int main(char argc, char* argv)
{pthread_t ptid[2] = {};struct sockaddr_in client_sk;if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) ==-1) {perror("Create socket");exit(1);}bzero(&client_sk, sizeof(struct sockaddr_in));client_sk.sin_family = AF_INET;client_sk.sin_port = htons(PORT);client_sk.sin_addr.s_addr = htonl(INADDR_ANY); if((connect(sockfd, (struct sockaddr*)&client_sk, sizeof(struct sockaddr))) == -1) {perror("Connect server");exit(1);}bzero(&send_msg, sizeof(send_msg));printf("请输入您的昵称:");scanf("%s", send_msg.name);if((pthread_create(&ptid[0], NULL, pthread_recv, NULL)) != 0) {perror("pthread create recv");pthread_exit(NULL);}if((pthread_create(&ptid[1], NULL, pthread_send, NULL)) !=0) {perror("pthread create send");pthread_exit(NULL); }while(!quit);close(sockfd);
}
Makefile
all:gcc -o client client.c -lpthreadgcc -o server server.c -lpthread
运行服务端
运行客户端A,昵称:刘备
运行客户端B,昵称:关羽
基于Linux下TCP/IP协议局域网聊天室相关推荐
- java毕业设计——基于java+TCP+UDP的局域网聊天室系统设计与实现(毕业论文+程序源码)——局域网聊天室系统
基于java+TCP+UDP的局域网聊天室系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+TCP+UDP的局域网聊天室系统设计与实现,文章末尾附有本毕业设计的论文和源码下载地 ...
- 基于UDP/IP协议的聊天室
基于TCP/IP通信协议的聊天室 概述: 基于TCP/IP通信协议的聊天室是通过服务端/客户端的模式进行的,必须是服务端开启之后,客户端通过获取服务端的ip和端口号并连接之后才能进行信息的共享,具体的 ...
- linux中tcp/ip协议实现及嵌入式应用 下载,LINU中TCPIP协议实现及嵌入式应用
好文网为大家准备了关于LINU中TCPIP协议实现及嵌入式应用范文,好文网里面收集了五十多篇关于好LINU中TCPIP协议实现及嵌入式应用好文,希望可以帮助大家.更多关于LINU中TCPIP协议实现及 ...
- 基于C#的TCP/IP协议应用(一)
一.背景与概念 1.标准以太网 以太网是美国Xerox(施乐)公司的Palo Alto研究中心于1975年研制成功的,其核心技术起源于ALOHA网.目前以太网是指符合IEEE 802.3标准的局域网( ...
- Linux下TCP/IP优化
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握 ...
- Linux --OSI TCP/IP协议族
OSI简介 简介 OSI Open System Interconnection 开放系统互联模型 开放式系统互联 国际标准化组织(ISO)制定 定义了不同计算机互联的标准 设计和描述,计算机网络通信 ...
- 回顾下TCP/IP协议
首先要知道什么是TCP/IP协议,从字面意思来看TCP是"Transmission Control Protocol"的缩写,也就是传输控制协议.IP是"Internet ...
- Linux下Select多路复用实现简易聊天室
前言 和之前的udp聊天室有异曲同工之处,这次我们客户端send的是一个封装好了的数据包,recv的是一个字符串,服务器recv的是一个数据包,send的是一个字符串,在用户连接的时候发送一个logi ...
- linux tcp ip c,Linux下TCP/IP编程--TCP实战(select)
本文参考自徐晓鑫<后台开发>,记录之. 一.为什么要使用非阻塞I/O之select 初学socket的人可能不爱用select写程序,而习惯诸如connect.accept.recv/re ...
最新文章
- 2021-10-11 二叉树中查找值为key的结点
- 数字三角形问题 (动态规划初步)
- C# 网络编程之通过ip地址获取地理位置(补充)
- OpenFOAM流固耦合问题-FsiFoam(foam-extend-4.0)运行tutorials的bug修复
- 华为防火墙Edumon1000E配置
- react16.8+的生命周期
- 大数据分块_谷歌卫星影像金字塔分块下载原理说明
- HDU2795 billboard【转化为线段树。】
- java留言板_java实现简单留言板功能的代码实例
- 【vue源码工程阅读1:下载源码】认识工程并打包
- YML解析框架SnakeYaml简介
- 《心经》-翻译、中英梵对照
- msdn原版系统和原版office
- k8s节点NotReady问题定位
- 2021-01-30
- 数据结构与算法笔记:贪心策略之BSTBBST, Hashtable+Dictionary+Map, Priority Queue~Heap, Minium Spanning Tree
- 家庭版Windows10/Windows11不支持远程桌面的解决办法
- 组合拳砸来:55位权威专家论剑股市!
- 如何区别药品的通用名、商品名(品牌名)和别名?
- CNI-Terway讲解