1. 程式人生 > >Linux下基於TCP的聊天室

Linux下基於TCP的聊天室

能夠實現簡單的多人聊天和私聊

伺服器接收來自客戶端的連線請求,當有客戶端傳送過來資料時,伺服器將資料儲存到全域性緩衝區,並將資料迴圈傳送給已經連線的客戶端

不解釋直接上程式碼:

伺服器:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>

#define PORT 8081				//設定埠資訊	
#define BUFFER_SIZE 1024		//設定最大發送資訊位元組
#define MAX_SIZE 10			//最大連線數

struct Msg{				//傳送訊息的結構體包含姓名 傳送的資訊 該客戶端的套接字描述符
	
	char name[20];
	char message[BUFFER_SIZE];
	int socket;
	int flge;

};

int connfd[MAX_SIZE];    //把連線進來的客戶端放在陣列中

void *recv_fun(void *arg); //接受資訊函式

int main()
{
	struct sockaddr_in sin,cin; //宣告兩個套接字
	
	int sfd,cfd;
	
	int Length = sizeof(struct sockaddr_in); //套接字結構體的大小
	
	//char buf[BUFFER_SIZE];   
	
	int n;
	
    if((sfd=socket(AF_INET,SOCK_STREAM,0))==-1){		//建立套接字
		
		printf("socket error\n");
		
		exit(1);
	}
	
	//為套接字設定ip協議 設定埠號  並自動獲取本機ip轉化為網路ip
	sin.sin_family=AF_INET;
	
	sin.sin_port=htons(PORT);
	
	sin.sin_addr.s_addr=htonl(INADDR_ANY);
	
	bzero(&(sin.sin_zero),8);
	
	if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0){	//繫結套接字
	
		printf("bind error\n");
		
		exit(1);
		
	}
	
	printf("Bind success!\n");

	if(listen(sfd,MAX_SIZE)==-1){	//監聽最大連線數
	
		printf("listen error\n");
		
		exit(1);
	}
	
	printf("listening....\n");
	
	int i;
	
	for(i=0; i<MAX_SIZE; i++)   //剛開始先把存放客戶端的陣列設定初始值為-1
	
		connfd[i] = -1;
		
	
	printf("Weiting.......\n");
	
		//等待客戶端連線	
	
	while(1){
	
	
		int i;
		
		for(i=0; i<MAX_SIZE; i++){	//尋找到沒有儲存客戶端的一個位置
		
			if(connfd[i] == -1){
			
			break;
			
			}
		
		}
			//讓該位置儲存下一個連線進來的客戶端
		if((connfd[i]=accept(sfd, (struct sockaddr *)&cin, &Length)) == -1){//連線客戶端
		
			printf("accept error\n");
			
			exit(1);
		}else
		
		printf("有人加入編號為:%d\n", i);   //輸入連線進來的客戶端的編號
		
		pthread_t th1;
		
		pthread_create(&th1, NULL, recv_fun, (void*)&connfd[i]);   // 建立一個執行緒把接受資訊的函式加入到主函式中
		
	}
	
	
	return 0;
}

void *recv_fun(void *arg){

	int fd = *((int *)arg);		//用來儲存剛才發訊息過來的客戶端的編號
	
	struct Msg msg;		//宣告一個結構體用來接收發送過來的資訊
	
	int flge, num_send, num_recv;
	
	while(1){
		
		int n=recv(fd, (char*)&msg, sizeof(msg), 0);	//接受傳送過來的資訊儲存到msg的結構體中
		
		if(n<=0){//判斷是否接收成功
		
			printf("recv error\n");
			
			connfd[msg.socket] = -1;
			
			pthread_exit(NULL);
			
			exit(1);
			 
		}
		
		int i;
		
		for(i=0; i<MAX_SIZE; i++){  //如果客戶端要私聊的話,先遍歷陣列找到要私聊的客戶端的位置
		
			if(fd == connfd[i])
			
				break;
		}
		
		msg.socket = i;
		//在伺服器中顯示一下發送的資訊
		printf("接受到編號為:%d,%s訊息為:%s,\n\n\n", msg.socket, msg.name, msg.message);
		
		if(msg.flge == -1){//-1時為群聊
		
			for(i=0; i<MAX_SIZE; i++){//從開始位置一直找到最後一個存放客戶端的位置除去自己其他的客戶端都發送一邊資訊
				
				if(connfd[i] != fd && connfd[i] != -1){
					
					num_send=send(connfd[i], (char*)&msg, sizeof(msg), 0);
					
					if(num_send < 0){
					
						printf("send error\n");
					
					}	
				}
			}
		}else{//如果不是群聊的話就把資訊傳送給指定位置的客戶端上
		
			num_send=send(connfd[msg.flge], (char*)&msg, sizeof(msg), 0);
			
			if(num_send < 0 ){
				
				printf("send error\n");
			}
		
		} 
	
	}

}
客戶端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define PORT 8081		//設定埠資訊這是埠號要與伺服器埠號相同
#define BUFFER_SIZE 1024		//設定最大發送資訊位元組
#define HOST_ADDR "127.0.0.1"	//設定伺服器的ip因為都是本地連線即伺服器的埠為127.0.0.1

struct Msg{	//傳送資訊的結構體包含客戶端的資訊, 傳送訊息  套接字描述符 和要群發和私聊的判斷符
	
	char name[20];
	char message[BUFFER_SIZE];
	int socket;
	int flge;

};
struct Msg msg;

void *send_fun(void *arg);		//傳送資訊函式
void *recv_fun(void *arg);		//接受資訊函式

int main()
{
	int sfd;
	
	//char buf[BUFFER_SIZE];
	
	struct sockaddr_in sin;
	
	
   if((sfd=socket(AF_INET,SOCK_STREAM,0))==-1){//建立一個套接字AF_INET代表ipV4協議 SOCK_STREAM 是用TCP連線型別的有序位元組流協議
			printf("socket error\n");
			
			exit(1);
			
	}
		
	//設定套接字地址資訊AF_INET代表使用ipv4, htons(PORT)把本地埠轉化為網路埠s代表轉化為短型的 inte_pton函式就是把開始設定的ip轉化為網路的ip並使用ipv4協議給套接字sin的ip
	sin.sin_family=AF_INET;
	
	sin.sin_port=htons(PORT);
	
   inet_pton(AF_INET,HOST_ADDR,&sin.sin_addr);  
   
   /* if(inet_aton(HOST_ADDR,&sin.sin_addr)== -1)//與上面轉化一樣
    {
        printf("inet_aton error.\n");
        return -1;
    }
	*/
	
	bzero(&(sin.sin_zero),8);//為套接字補8個0
	
	if(connect(sfd,(struct sockaddr *)&sin,sizeof(sin))==-1)//連線客戶端,sfd為套接字描述符, 第二個引數表示把sockaddr_in型別的sin轉化為sockaddr型別的, 第三個引數為sin的位元組數
	{
		printf("connet error\n");
		
		close(sfd);
		
		exit(1);
	}
	
	printf("輸入姓名:");
	
	scanf("%s", msg.name);
	
	pthread_t th1, th2;	//宣告兩個執行緒變數
	
	//分別把send_fun函式和recv_fun函式加入到主函式中
	if(pthread_create(&th1, NULL, send_fun, (void*)&sfd)){
	
		perror("Create phtread error\n");
		
		exit(1);
	
	}
	
	if(pthread_create(&th2, NULL, recv_fun, (void*)&sfd)){
	
		perror("Create phtread error\n");
		
		exit(1);
	
	}
	//等待執行緒結束 
	pthread_join(th1, NULL);
	
	pthread_join(th2, NULL);
	
	close(sfd);
	
	return 0;
}
	
	
void *send_fun(void *arg){

	int sfd= *((int *)arg);
	
	
	while(1){
	
		printf("請選擇聊天方式:\n-1 群聊 \n輸入其他客戶端編號私聊\n請選擇:\n");
		
		scanf("%d", &msg.flge);//輸入標記符後面用來判斷是私聊還是群聊
		
		printf("輸入聊天內容:");
		
		scanf("%s", msg.message);//聊天資訊
		
		int n = send(sfd, (char *)&msg, sizeof(msg), 0);//傳送資訊
		
		if(n!= sizeof(msg)){
			
			perror("send error\n");
			
			exit(1);
		
		}
		
	}

}
	
	
void *recv_fun(void *arg){

	int sfd=*((int*)arg);
	
	struct Msg msg;
	
	while(1){
	
		int n=recv(sfd, (char*)&msg, sizeof(msg), 0);//接受資訊函式
	
		if(n == -1){
		
		perror("recv error\n");
		
		exit(1);
		
		}
		//輸出接受的資訊
		printf("\n編號為:%d, 姓名為:%s, 發的資訊為:%s\n\n", msg.socket, msg.name, msg.message);
		
	}

}



伺服器接收來自客戶端的連線請求,當有客戶端傳送過來資料時,

伺服器將資料儲存到全域性緩衝區,並將資料迴圈傳送給已經連線的客戶端

相關推薦

Linux基於TCP聊天

能夠實現簡單的多人聊天和私聊 伺服器接收來自客戶端的連線請求,當有客戶端傳送過來資料時,伺服器將資料儲存到全域性緩衝區,並將資料迴圈傳送給已經連線的客戶端 不解釋直接上程式碼: 伺服器: #include <stdio.h> #include <s

linux基於tcp的FTP程式設計

客戶端輸入: ls :           顯示本地檔案列表 service  ls:       顯示伺服器檔案列表 upload  xxx:      實現xxx檔案讀取與上傳 download  xxx :  實現xxx檔案下載與儲存 公共函式commonfunc.

Linux基於Socket網絡通信的多人聊天

data break arp pre font linu print lose types.h 服務端 #include <stdio.h> #include <sys/types.h> #include <sys/socket.h>

mini聊天Linux基於UDP實現的群聊系統)

一.原理 (1)客戶端從標準輸入讀取資料,將資料序列化後傳送至網路; (2)伺服器端使用多執行緒+生產者消費者模型; 生產者從網路中讀取資料,並將讀取到的使用者資訊新增至使用者列表,將資料放至資料池中; 消費者從資料池讀取資料,並廣播給所有在使用者列表中的使用者。

Linux基於UDP協議實現的聊天專案(附原始碼)

好久沒來更新了,這段時間一直在著手完成這個專案,由於之前沒有接觸過這種稍大型的專案,而且對於C/S架構以及UDP通訊的瞭解也不是很深,所以前面很大的一段時間都被浪費掉了,做了很大無用功。 剛開始弄的時候,也是在網上搜了很多資料,找了很多版本,發現大都有

網路程式設計專案:linux基於C/S架構的聊天

一、專案要求: 1. 採用 Client/Server 架構  2. Client A 登陸聊天伺服器前,需要註冊自己的 ID 和密碼  3. 註冊成功後,Client A 就可以通過自己的 ID 和密碼登陸聊天伺服器  4. 多個 Client X 可以同時登陸聊天伺服器

linux網路程式設計練習---聊天TCP/IP實現)

為了更深刻的鍛鍊認識TCP/IP協議,加強自己對Linux系統的網路程式設計部分的編寫程式碼能力,編寫基於控制檯的聊天視窗,用本機既當伺服器又當客戶端,先開啟一個shell,執行伺服器程式,然後再開啟一個shell視窗,執行客戶端程式,顯示連線成功,開始聊天吧。不知道為什麼

基於linux的區域網聊天

主執行緒:構造伺服器物件,建立libevent,監聽伺服器的監聽套接字;建立pth_nuum個socker_pair,加入到伺服器儲存的socker_pair_vector,將socket_pair的0端處理為繫結事件發生的回撥函式socketpair_cb(),全部事件加入到主執行緒libevent,而在s

linux基於lvs-dr模式的電子商務平臺搭建

linux lvs dr 1)環境準備一臺lvs服務器,兩臺以上實現了電子商務平臺的服務器作為realserver(之前博客有搭建過程)2)將realserver服務器的主機模式的網卡移除3)在lvs服務器上配置主機模式的網卡別名4)添加路由記錄5)開啟一個基於80端口的虛擬服務6)配置reals

【轉】LinuxTCP狀態機,三次握手判斷DDOS攻擊

pla rep img 實體 -s lar 連接狀態 sdn 類型 從TCP狀態機判斷DDOS攻擊 一、TCP協議 TCP 協議是傳送層的核心協議,提供了可靠面向連接的協議,分為三次握手和四次斷開,在這個過程中TCP有個狀態機,記錄不同階段的狀態。 二、 TCP握手和斷開

LinuxTCP/IP程式設計----多播和廣播的實現 【轉載】LinuxTCP/IP程式設計----多播和廣播的實現

【轉載】 出處:https://blog.csdn.net/wqc_CSDN/article/details/51588769 【轉載】Linux下的TCP/IP程式設計----多播和廣播的實現

linux基於vc088x開發板分析CLK模型(時鐘管理)

Linux clk 模型   Linux clk模型採用面向物件的思想來設計實現的。 在porting層建立一個一個的clk節點物件,然後將所有的clk節點物件連成一個list。 當驅動層需要設定時鐘的時候,通過porting層與驅動層

linux基於docker環境安裝mysql

二、安裝mysql 1、docker拉取mysql的映象,構建映象,啟動映象 https://www.cnblogs.com/loovelj/p/7823093.html 命令列啟動mysql例項 d

LinuxTCP/IP程式設計多播和廣播的實現

【轉載】 【轉載】Linux下的TCP/IP程式設計----多播和廣播的實現 2016年06月05日 13:54:10 兜裡有糖心裡不慌 閱

linux基於laravel框架基礎上安裝後臺管理系統laravel-admin(1.4)

1,首先需要安裝laravel框架(composer安裝). laravel框架和擴充套件均存放在composer依賴資源庫中,composer類似git庫。所以安裝laravel就必需先安裝composer。 Composer是一個PHP編寫的依賴資源管理器,需要PHP 5.3.2+才能執行(需要開啟o

linuxTCP小程式

服務端是用多執行緒寫的併發伺服器,比較簡單。 功能: 1.  服務端執行後,即監聽指定的埠。允許多個連線併發執行 2.  服務端接收到客戶端請求後,根據客戶端傳過來的指令完成特定任務: a)         向客戶端傳送服務端所在機器的當前時間 b)        向客戶

Linux C基於TCP的網路程式設計(三次握手)

網路通訊(TCP) TCP(面向連線的通訊協議):在通訊中時刻保持連線,這種通訊方式類似於打電話,能保證安全可靠資料不丟失,但是與UDP相比傳輸速度較低。 TCP和UDP通訊收發函式區別:記住socket中是否存放有IP 和埠資訊,TCP有,UDP無。同時T

tcp聊天[天上人間] V2.0版本

用tcp套接字搭建聊天室 import socket def main(): #1.建立tcp套接字 tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #2.繫結本地資訊(bind) tcp_soc

linux 多執行緒聊天

(1)linux下使用多執行緒編寫的聊天室 https://www.cnblogs.com/Newdawn/p/5509687.html (2)基於TCP的聊天室 https://blog.csdn.net/weixin_41413441/article/details/80156696

Linux基於Eclipse搭建STM32開發環境

以下內容參考自摩爾吧“Linux+Eclipse開發STM32”視訊教程。 下載gcc-arm-none-eabi-gcc壓縮包 配置ARM交叉編譯鏈 安裝eclipse 新建工程進行測試(需要編