国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

多人聊天室(帶私聊功能)Linux網(wǎng)絡(luò)編程基礎(chǔ)

這篇具有很好參考價值的文章主要介紹了多人聊天室(帶私聊功能)Linux網(wǎng)絡(luò)編程基礎(chǔ)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

在和同學(xué)一起努力下終于完成了期末作業(yè)哈哈哈哈

文章目錄

目錄

前言

一、需求分析

二、功能設(shè)計

1.服務(wù)器端:

2.客戶端:

三、流程圖:

編程流程圖:

服務(wù)器流程圖:

客戶端流程圖:

四、運行效果:

項目源碼:

服務(wù)器源碼

客戶端源碼:

總結(jié):


前言

Linux網(wǎng)絡(luò)編程是我們這學(xué)期學(xué)習(xí)嵌入式的重要內(nèi)容

不僅僅是期末作業(yè),更是對linux網(wǎng)絡(luò)編程的鞏固。

接下來我會將全部內(nèi)容分享出來哈哈ψ(`?′)ψ

提示:完成得比較隨意,不夠嚴(yán)謹(jǐn),僅供參考,大家都能做得更好!


一、需求分析

? ? ? ?需要一個可以實現(xiàn)多人同時在線的聊天室網(wǎng)絡(luò)應(yīng)用,用戶各自在登錄時自定義一個網(wǎng)名,并以這個網(wǎng)名在多人聊天室中與別人聊天,同時每個用戶可以通過用戶名辨別其他用戶。

? ? ? ?用戶還可以通過已知的用戶名,與指定用戶進行私聊(僅限對方可見)。

(走個流程)

二、功能設(shè)計

一個能容納多人在線聊天的聊天室的網(wǎng)絡(luò)應(yīng)用程序,包括客戶端與服務(wù)器端:

1.服務(wù)器端:

服務(wù)器端:能同時接受多用戶的登陸,并將每個用戶的聊天信息廣播到其他用戶;廣播的時候會附加上發(fā)言的用戶名;

2.客戶端:

客戶端:用戶能夠以` client name` 的命令行程序運行,并以`name`的用戶名登陸聊天室(不需要密碼);客戶端能允許用戶發(fā)言,并實時接收服務(wù)器的廣播信息;當(dāng)客戶端輸入`quit`時,退出客戶端;客戶端具備私聊的功能,當(dāng)A用戶需要向B用戶(假設(shè)`B`為用戶名)私聊時,使用命令`send:B:message` 發(fā)送聊天信息;服務(wù)器會把該信息發(fā)送給B用戶;


三、流程圖:

編程流程圖:

多人聊天室(帶私聊功能)Linux網(wǎng)絡(luò)編程基礎(chǔ)

服務(wù)器流程圖:

多人聊天室(帶私聊功能)Linux網(wǎng)絡(luò)編程基礎(chǔ)

客戶端流程圖:

多人聊天室(帶私聊功能)Linux網(wǎng)絡(luò)編程基礎(chǔ)


四、運行效果:

先運行服務(wù)器端,然后在其他終端分別運行客戶端即可:

如圖:三個用戶分別進入聊天室,系統(tǒng)均會進行廣播通知,并顯示當(dāng)前在線人數(shù),當(dāng)其中一個客戶端運行時,會先注冊登錄(無需密碼)。

A?和 B 分別在群聊中發(fā)送消息,消息均在各個客戶端顯示;A 向 C 單獨發(fā)送私聊悄悄話,僅C的客戶端能看見A發(fā)來的消息,說明私聊功能實現(xiàn)。

 截圖

多人聊天室(帶私聊功能)Linux網(wǎng)絡(luò)編程基礎(chǔ)


項目源碼:

服務(wù)器源碼

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#define BUF_SIZE (4096)
#define SEM_SIZE (20) // 群聊上限人數(shù)

// 信號量--判斷群聊人數(shù)
sem_t sem;
// 服務(wù)端文件描述符
int svr_fd;
// 存儲群友,多一個是為了當(dāng)群人滿時,空一個出來接發(fā)信息
int cli_fd[SEM_SIZE + 1] = {};

struct client
{
	/* data */
	char buf[BUF_SIZE];	 // message
	char name[BUF_SIZE]; // name
	int client_fd;		 // fd
};

struct client clients[SEM_SIZE];

// 字符串分割函數(shù)
void split(char *src, const char *separator, char **dest, int *num)
{
	char *pNext;
	// 記錄分隔符數(shù)量
	int count = 0;
	// 原字符串為空
	if (src == NULL || strlen(src) == 0)
		return;
	// 未輸入分隔符
	if (separator == NULL || strlen(separator) == 0)
		return;
	/*
		c語言string庫中函數(shù),
		聲明:
		char *strtok(char *str, const char *delim)
		參數(shù):
		str -- 要被分解成一組小字符串的字符串。
		delim -- 包含分隔符的 C 字符串。
		返回值:
		該函數(shù)返回被分解的第一個子字符串,如果沒有可檢索的字符串,則返回一個空指針。

	*/
	char *strtok(char *str, const char *delim);
	// 獲得第一個由分隔符分割的字符串
	pNext = strtok(src, separator);
	while (pNext != NULL)
	{
		// 存入到目的字符串?dāng)?shù)組中
		*dest++ = pNext;
		++count;
		/*
			strtok()用來將字符串分割成一個個片段。參數(shù)s指向欲分割的字符串,參數(shù)delim則為分割字符串中包含的所有字符。
			當(dāng)strtok()在參數(shù)s的字符串中發(fā)現(xiàn)參數(shù)delim中包涵的分割字符時,則會將該字符改為\0 字符。
			在第一次調(diào)用時,strtok()必需給予參數(shù)s字符串,往后的調(diào)用則將參數(shù)s設(shè)置成NULL。
			每次調(diào)用成功則返回指向被分割出片段的指針。

		*/
		pNext = strtok(NULL, separator);
	}
	*num = count;
}

// 群發(fā)函數(shù)
void *send_all(char *buf)
{
	for (int i = 0; i < SEM_SIZE; i++)
	{
		// 若值為-1,則沒有此群友,表示已經(jīng)退出或未被占有
		if (-1 != cli_fd[i])
		{
			printf("%s\n", buf);
			printf("send to %d\n", cli_fd[i]);
			write(cli_fd[i], buf, strlen(buf) + 1);
		}
	}
}

/**
 * 發(fā)送給指定的用戶
 * char *buf 發(fā)送的消息
 * int fd 發(fā)給誰
 */
void *send_one(char *buf, int fd)
{
	printf("send to %d : %s\n",fd, buf);
	// printf("send to %d\n", fd);
	write(fd, buf, strlen(buf) + 1);
}

// 服務(wù)端接收函數(shù)
void *server(void *arg)
{

	int fd = *(int *)arg;
	char buf[BUF_SIZE];
	char name[BUF_SIZE], ts[BUF_SIZE];
	
	

	// 獲取昵稱
	read(fd, clients[fd].name, sizeof(name));
	clients[fd].client_fd = fd;

	// printf("clients[fd].name = %s\n", clients[fd].name);
	printf("存放clients[fd].client_fd = %d\n", clients[fd].client_fd);
	sprintf(ts, "[system]熱烈歡迎 %s 進入群聊", clients[fd].name);
	send_all(ts);

	for (;;)
	{
		// 接收信息,無信息時將阻塞
		int recv_size = read(fd, clients[fd].buf, sizeof(buf));

		
		// 收到退出信息
		if (0 >= recv || NULL != strstr(clients[fd].buf, "quit"))
		{
			sprintf(ts, "[system]歡送 %s 離開群聊\n", clients[fd].name);
			int index = 0;
			// 找到要退出的那個人,并將其置為-1
			for (; index < SEM_SIZE; index++)
			{
				if (cli_fd[index] == fd)
				{
					cli_fd[index] = -1;
					break;
				}
			}
			// 群發(fā)XXX退出聊天室提示消息
			send_all(ts);

			// 群友退出,信號量+1
			int n;
			sem_post(&sem);
			sem_getvalue(&sem, &n);

			printf("[system] %s 離開群聊,群聊還剩%d人\n", clients[fd].name, SEM_SIZE - n);
			strcpy(clients[fd].buf, "quit");

			write(fd, clients[fd].buf, strlen(clients[fd].buf) + 1);
			close(fd);
			pthread_exit(NULL);
		}

		// 單獨發(fā)送或者群發(fā)
		//    ------/send name message
		if (0 >= recv || NULL != strstr(clients[fd].buf, "send"))// 單獨發(fā)
		{ 	
			char str[100];
			char *p[10]={0};
			int num=0,i;
			//拷貝
			strcpy(str,clients[fd].buf);
			// printf("clients[fd].buf1 = %s\n", clients[fd].buf); //send name message
			// 對 clients[fd].buf進行截取
			split(clients[fd].buf,":",p,&num);
			// printf("clients[fd].buf1 = %s\n", clients[fd].buf); //send
			// printf("split str is = %s\n",p[1]);
			// 然后遍歷數(shù)組進行比較 找到和name相同的數(shù)組元素,取出來進行發(fā)送
			for(i = 0;i < SEM_SIZE; i++) {


                                // 判斷名字,去除對應(yīng)client_fd進行發(fā)送
				if(NULL != strstr(clients[i].name,p[2])){
					printf("client[%d].name3 = %s\n",i,clients[i].name);
					char msg[200];
					sprintf(msg,"[悄悄話]%s:%s",clients[fd].name,p[3]);
					send_one(msg, clients[i].client_fd);
                                }
                        }
		}
		else
		{ // 群發(fā)
			send_all(clients[fd].buf);
		}
	}
}

/**
 * quit
 */
void sigint(int signum)
{
	close(svr_fd);
	sem_destroy(&sem);
	printf("[system]服務(wù)器關(guān)閉\n");
	exit(0);
}

int main()
{
	signal(SIGINT, sigint);
	// 初始化信號量,群聊上限SEM_SIZE人
	sem_init(&sem, 0, SEM_SIZE);

	// 創(chuàng)建socket對象
	printf("[system]創(chuàng)建socket對象...\n");
	svr_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (0 > svr_fd)
	{
		perror("socket");
		return -1;
	}


	//端口復(fù)用函數(shù):解決端口號被系統(tǒng)占用的情況
	int on = 1;
	int gg = setsockopt(svr_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
	if(gg==-1)
	{
		perror("setsockopt");
		return -1;
	}

	// 準(zhǔn)備通信地址(自己)
	printf("[system]準(zhǔn)備通信地址...\n");
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(6666);
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	socklen_t addrlen = sizeof(addr);

	// 綁定socket對象與地址
	printf("[system]綁定socket對象與地址...\n");
	if (bind(svr_fd, (struct sockaddr *)&addr, addrlen))
	{
		perror("bind");
		return -1;
	}

	// 設(shè)置監(jiān)聽和排除數(shù)量
	printf("[system]設(shè)置監(jiān)聽");
	if (listen(svr_fd, 10))
	{
		perror("listen");
		return -1;
	}

	printf("[system]等待客戶端鏈接...\n");
	// 將初始值置全為-1,表示該聊天位置沒有人占領(lǐng)
	memset(cli_fd, -1, sizeof(cli_fd));
	for (;;)
	{
		int sem_num;
		sem_getvalue(&sem, &sem_num);

		// 找到?jīng)]有人占領(lǐng)的聊天位
		int index = 0;
		while (-1 != cli_fd[index])
			index++;
		cli_fd[index] = accept(svr_fd, (struct sockaddr *)&addr, &addrlen);

		if (0 > cli_fd[index])
		{
			perror("accept");
			return -1;
		}

		char buf[BUF_SIZE];
		if (0 >= sem_num)
		{
			printf("[system]人數(shù)已滿,%d號客戶端鏈接失敗\n", cli_fd[index]);
			sprintf(buf, "[system]人數(shù)已滿,客戶端鏈接失敗");
			write(cli_fd[index], buf, strlen(buf) + 1);
			close(cli_fd[index]);
			cli_fd[index] = -1;
		}
		else
		{
			sem_trywait(&sem);
			sem_getvalue(&sem, &sem_num);
			char msg[BUF_SIZE] = {};
			printf("[system]%d號客戶端鏈接成功,當(dāng)前聊天人數(shù)%d人\n", cli_fd[index], SEM_SIZE - sem_num);
			sprintf(msg, "[system]客戶端鏈接成功,當(dāng)前聊天人數(shù)%d人\n", SEM_SIZE - sem_num);
			write(cli_fd[index], msg, strlen(msg) + 1);

			// 創(chuàng)建線程客戶端
			pthread_t tid;
			pthread_create(&tid, NULL, server, &cli_fd[index]);
		}
	}
}

客戶端源碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define BUF_SIZE (4096)


/**
 * 讀取server轉(zhuǎn)發(fā)過來的消息
*/
void* client_read(void* arg)
{
	int cli_fd = *(int*)arg;
	char buf[BUF_SIZE];
	
	//接收數(shù)據(jù)
	for(;;)
	{
		int recv_size = read(cli_fd,buf,BUF_SIZE);
		if(0 >= recv_size || 0 == strcmp(buf,"quit"))
		{
			printf("已經(jīng)與服務(wù)器斷開鏈接\n");
			pthread_exit(NULL);
		}
		printf("%s\n",buf);
	}
}

int main()
{
	//創(chuàng)建socket對象
	printf("創(chuàng)建socket對象...\n");
	int cli_fd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > cli_fd)
	{
		perror("socket");
		return -1;
	}
	
	//準(zhǔn)備通信地址(服務(wù)端)
	printf("準(zhǔn)備通信地址...\n");
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(6666);
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");//此處填寫自己的ip地址
	socklen_t addrlen = sizeof(addr);
	
	//鏈接服務(wù)端
	printf("鏈接服務(wù)端口...\n");
	if(connect(cli_fd,(struct sockaddr*)&addr,addrlen))
	{
		perror("connect");
		return -1;
	}
	
	char buf[BUF_SIZE];
	
	read(cli_fd,buf,BUF_SIZE);
	if(NULL == strstr(buf,"鏈接成功"))
	{
		printf("群聊人已滿,請稍后再來\n");
		close(cli_fd);
		return 0;
	}
	printf("%s\n",buf);
	
	//鏈接成功,創(chuàng)建客戶端
	pthread_t tid;
	pthread_create(&tid,NULL,client_read,&cli_fd);
	
	//輸入昵稱
	char name[BUF_SIZE] = {};
	printf("請輸入你的昵稱:");
	gets(name);
	write(cli_fd,name,strlen(name)+1);
	
	//發(fā)送數(shù)據(jù)
	for(;;)
	{
		printf(">>");
		gets(buf); // 獲取鍵盤字符串
		
		char msg[BUF_SIZE]; // 存儲格式化后的字符串
		sprintf(msg,"%s:%s",name,buf); // 輸出字符串
		
		//把msg發(fā)送到cli_fd
		int send_size = write(cli_fd,msg,strlen(msg)+1);
		// 如果字符串是quit就退出
		if(0 >= send_size || 0 == strcmp(buf,"quit"))
		{
			printf("結(jié)束通信\n");
			close(cli_fd);
			pthread_exit(NULL);
			return 0;
		}
	}
}

總結(jié):

太好咯,又做完一個作業(yè) 哈哈哈O(∩_∩)O文章來源地址http://www.zghlxwxcb.cn/news/detail-491315.html

到了這里,關(guān)于多人聊天室(帶私聊功能)Linux網(wǎng)絡(luò)編程基礎(chǔ)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 使用Linux系統(tǒng)IO多路復(fù)用中eopll創(chuàng)建基于TCP通信協(xié)議的多人聊天室

    一.1.搭建好TCP的通信模型 2.創(chuàng)建紅黑樹根節(jié)點?3.將套接字事件添加到紅黑樹中,使其被監(jiān)聽 4.當(dāng)套接字事件發(fā)生,表示有客戶端連接,將連接事件加入到紅黑樹節(jié)點當(dāng)中 5.每當(dāng)連接事件發(fā)生時,表示客戶端發(fā)送信息到服務(wù)器 6.每當(dāng)有事件準(zhǔn)備就緒時,將對應(yīng)的紅黑樹節(jié)點信息

    2024年02月13日
    瀏覽(19)
  • Python多人聊天室

    Python多人聊天室

    鏈接:https://pan.baidu.com/s/1kzxiLTkvdxGAMgF3SQzcaw?pwd=vb9h 提取碼:vb9h 利用socket方式編寫一個多人聊天室程序,可以實現(xiàn)多個用戶之間的群聊功能,私聊功能,顯示當(dāng)前用戶功能 在聊天室程序中增加利用ftp實現(xiàn)文件的上傳,下載,刪除,查看當(dāng)前文件功能 在聊天室程序中增加利用

    2024年02月03日
    瀏覽(88)
  • Java 多人聊天室

    Java 多人聊天室

    Java實訓(xùn)做的多人聊天室,效果如圖: 能夠?qū)崿F(xiàn)多個客戶端之間的互相聊天,服務(wù)端來負責(zé)接收數(shù)據(jù)和轉(zhuǎn)發(fā)數(shù)據(jù)。 每個客戶端可以自己設(shè)置和修改自己的名稱,并傳給服務(wù)器讓其他客戶端知道。 當(dāng)有客戶端加入和退出時,群聊里每個客戶端都有提示。(優(yōu)化了異常檢測,意外

    2024年02月10日
    瀏覽(21)
  • 【Java socket編程】多人聊天室

    【Java socket編程】多人聊天室

    課程設(shè)計大作業(yè) 功能: 1.具有 點對點通信 功能,任意客戶端之間能夠發(fā)送消息。 2.具有 群組通信 功能: 客戶端可以 自主建立群組 ,添加或刪除組成員; 客戶端能夠向組內(nèi)成員同時發(fā)送消息,其他組成員不能收到。 3.具有 廣播 功能 客戶端能夠向所有其他成員 廣播消息

    2024年02月04日
    瀏覽(35)
  • 基于Python web的多人聊天室

    基于Python web的多人聊天室

    ? ????????本文介紹了基于即時通訊的Python實現(xiàn)web版多人聊天室的設(shè)計和實現(xiàn)。這個系統(tǒng)利用了多種先進的技術(shù),如Django、Channels、WebSocket,來實現(xiàn)即時通信,并利用MySQL和Redis作為數(shù)據(jù)庫,同時還采用了多種前端技術(shù),如bootstrap、CSS、html和js,來提供出色的用戶體驗。該系

    2024年02月16日
    瀏覽(18)
  • vue3-多人聊天室角色識別(全棧)

    vue3-多人聊天室角色識別(全棧)

    主要技術(shù)棧是vue3,springboot,websocket,element-plus 主要目的是復(fù)習(xí)和梳理 發(fā)送信息,包裝信息,轉(zhuǎn)json,用socket發(fā)送到后端,使輸入欄清空 后端解析json,因為是socket接口,所以不能用@requestbody解析json,用以下方式解析json 設(shè)置發(fā)送時間為當(dāng)前時間,然后執(zhí)行mapper數(shù)據(jù)庫插入 廣

    2024年02月11日
    瀏覽(32)
  • Python多人聊天室-基于socket UDP協(xié)議

    Python多人聊天室-基于socket UDP協(xié)議

    使用Python編寫的基于socket UDP通信的多功能即時聊天室,包含Tkinter編寫的圖形化聊天界面,功能包括有賬號注冊和登錄,登錄成功后可以查看在線用戶,并和聊天室內(nèi)的其他在線用戶聊天,包含私聊和群發(fā),能發(fā)送文字、表情包,以及文件等。 登錄和注冊 顯示在線用戶 群聊

    2024年02月11日
    瀏覽(20)
  • C語言實現(xiàn)--基于UDP的多人在線聊天室

    C語言實現(xiàn)--基于UDP的多人在線聊天室

    目錄 實現(xiàn)功能 實現(xiàn)思想 實現(xiàn)代碼(部分及詳解) 服務(wù)端部分代碼 客戶端部分代碼 實現(xiàn)效果 項目中出現(xiàn)的問題和解決方法 項目整體代碼展示 代碼優(yōu)化思路 服務(wù)端代碼 客戶端代碼 服務(wù)端可以同時連接多個客戶端; 新的客戶端連接服務(wù)端時,可以在服務(wù)端顯示自己的名字并

    2024年02月04日
    瀏覽(27)
  • 基于Python guI的多人聊天室的設(shè)計與實現(xiàn)

    基于Python guI的多人聊天室的設(shè)計與實現(xiàn)

    現(xiàn)在,即時聊天系統(tǒng)已成為 Internet 上的主要交流工具,并且涌現(xiàn)出大量的AP和平臺。這些AP和平臺都擁有更加完善的交換機制,使得人們可以更加便捷地進行溝通和交換信息。 廣域網(wǎng)的聊天系統(tǒng)多重多樣,知名的軟件主要有 Facebook、騰訊 QQ 等。局域網(wǎng)聊天通信軟件也有很多,

    2024年02月05日
    瀏覽(20)
  • WebSocket+Vue實現(xiàn)簡易多人聊天室 以及 對異步調(diào)用的理解

    WebSocket+Vue實現(xiàn)簡易多人聊天室 以及 對異步調(diào)用的理解

    代碼倉庫:github ??HTTP是不支持長連接的,WebSocket是一種通信協(xié)議,提供了在單一、長連接上進行全雙工通信的方式。它被設(shè)計用于在Web瀏覽器和Web服務(wù)器之間實現(xiàn),但也可以用于任何需要實時通信的應(yīng)用程序。使用ws作為協(xié)議標(biāo)識符,如果需要加密則使用wss作為協(xié)議標(biāo)識符

    2024年01月17日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包