1. 程式人生 > >linux c 基於UDP的多人聊天程式

linux c 基於UDP的多人聊天程式

client.c

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

#define N 128

typedef struct
{
	char type;
	char name[32];
	char text[N];
}MSG;

int main(int argc,char *argv[])
{
	int socketfd;
	socklen_t addr_len;
	pid_t pid;
	MSG msg;
	struct sockaddr_in server_addr;
	if(argc < 3)
	{
		printf("uasge: %s ip port\n",argv[0]);
		exit(-1);
	}

	if((socketfd = socket(PF_INET,SOCK_DGRAM,0)) < 0)
	{
		perror("socket");
		exit(-1);
	}
	printf("input name:\n");
	fgets(msg.name,64,stdin);
	msg.name[strlen(msg.name) - 1] = '\0';
	msg.type='L';

	memset(&server_addr,0,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr(argv[1]);
	server_addr.sin_port = htons(atoi(argv[2]));
	addr_len = sizeof(server_addr);
	
	if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,addr_len) < 0)
	{
		perror("sendto3");
		exit(-1);
	}

	if((pid = fork()) == -1 )
	{
		perror("fork");
		exit(-1);
	}
	if(pid == 0)
	{
		while(1)
		{
			fgets(msg.text,N,stdin);
			msg.text[strlen(msg.text) - 1] = '\0';

			if(strncmp(msg.text,"quit",4) == 0)
			{
				msg.type = 'Q';
				if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,addr_len) < 0)
				{
					perror("sendto2");
					exit(-1);
				}
				kill(getppid(),SIGKILL);
				break;	
			}
			else
			{
				msg.type='B';
				if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,addr_len) < 0)
				{
					perror("sendto1");
					exit(-1);
				}	
			}
		
		}
		close(socketfd);
	}

	if(pid > 0)
	{
		while(1)
		{
			if(recvfrom(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,&addr_len) < 0)
			{
				perror("recvfrom");
				exit(-1);
			}
		
			switch(msg.type)
			{
				case 'L':
					printf("%s login\n",msg.name);
					break;
				case 'B':
					printf("from %s> %s\n",msg.name,msg.text);
					break;
				case 'Q':
					printf("%s quit\n",msg.name);
					break;
			}
		}
	}	
	return 0;
}
server.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>

#define N 128
#define L 1
#define B 2
#define Q 3

typedef struct 
{
	char type;
	char name[32];
	char text[N];
}MSG;

typedef struct node
{
	struct sockaddr_in addr;
	struct node *next;
}listnode,*linklist;

linklist linklist_create()
{
	linklist H;
	H = (linklist)malloc(sizeof(listnode));
	memset(H,0,sizeof(listnode));
	H->next = NULL;
	return H;
}

void  insert_data(linklist H,struct sockaddr_in client_addr)
{
	linklist p = NULL;
	p =(linklist)malloc(sizeof(listnode));
	p->addr = client_addr;
	p->next = H->next;
	H->next = p;
	return ;
}

void process_login(int socketfd,linklist H,MSG msg,struct sockaddr_in client_addr)
{
	insert_data(H,client_addr);
	linklist h1 = H;
	while(h1->next != NULL)
	{
		h1 = h1->next;

		if(memcmp(&client_addr,&h1->addr,sizeof(client_addr)) != 0 )
		{
			if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&(h1->addr),sizeof(h1->addr)) < 0)
			{
				perror("sendto4");
				exit(-1);
			}
		}
	}
	return ;
}

void process_broadcast(int socketfd,linklist H,MSG msg,struct sockaddr_in client_addr)
{
	linklist h1 = H;
	while(h1->next != NULL)
	{
		h1 = h1->next;
		if(memcmp(&client_addr,&h1->addr,sizeof(client_addr)) != 0)
		{
			if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&(h1->addr),sizeof(h1->addr)) < 0)
			{
				perror("sendto3");
				exit(-1);
			}
		}
	}
	return ;
}

void process_quit(int socketfd,linklist H,MSG msg,struct sockaddr_in client_addr)
{
	linklist p = H;
	linklist q;
	while(p->next)
	{
		if(memcmp(&client_addr,&p->next->addr,sizeof(client_addr)) == 0)
		{
			q = p->next;
			p->next = q->next;
			free(q);
			q = NULL;
		}
		else
		{
			if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->next->addr,sizeof(p->next->addr)) < 0)
			{
				perror("sendto");
				exit(-1);
			}
			p = p->next;
		}
	}
	return ;
}

int main(int argc,char *argv[])
{
	int socketfd;
	socklen_t addr_len;
	pid_t pid;
	MSG msg;
	struct sockaddr_in server_addr,client_addr;
	if(argc < 3)
	{
		printf("uasge: %s ip port\n",argv[0]);
		exit(-1);
	}

	memset(&server_addr,0,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr(argv[1]);
	server_addr.sin_port = htons(atoi(argv[2]));
	if((socketfd = socket(PF_INET,SOCK_DGRAM,0)) < 0)
	{
		perror("socket");
		exit(-1);
	}

	if(bind(socketfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0)
	{
		perror("bind");
		exit(-1);
	}
	addr_len = sizeof(client_addr);
	linklist H = linklist_create();

	if((pid = fork()) == -1)
	{
		perror("fork");
		exit(-1);
	}
	if(pid == 0)
	{
		while(1)
		{
			fgets(msg.text,N,stdin);
			msg.text[strlen(msg.text)-1] = '\0';
			strcpy(msg.name,"server");
			msg.type = 'B';
			if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0)
			{
				perror("sendto1");
				close(socketfd);
				exit(-1);
			}

		}
	}
	else if(pid > 0)
	{
		while(1)
		{
			if(recvfrom(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&client_addr,&addr_len) < 0)
			{
				perror("recvfrom");
				close(socketfd);
				exit(-1);
			}
		
			switch(msg.type)
			{
				case 'L':
					process_login(socketfd,H,msg,client_addr);
					break;
				case 'B':
					process_broadcast(socketfd,H,msg,client_addr);
					break;
				case 'Q':
					process_quit(socketfd,H,msg,client_addr);
					break;
			}
		}
	}

	return 0;
}

執行時須帶兩個引數 第一個是ip 第二個是埠

程式流程圖及主要結構體

typedef struct msg

{

char type; //訊息型別

char name[N]; //客戶名稱

char text[N]; //訊息正文

}MSG;

typedef struct node //存放客戶端的IP的連結串列

{

struct sockaddr_in addr;

struct node *next;

}listnode, *linklist;


相關推薦

Qt實用技巧:基於tcp的C/S構架聊天程式(線上、離線、離線資訊再次登入後傳送等)

需求         多人聊天室程式,基於TCP和C/S構架,需要離線後可對離線者傳送資訊,待離線者上線後可收到上次傳送的離線資訊 技術點     1.TCP連線伺服器     2.伺服器得儲存所有客戶端列表,包括線上的不線上的     3.伺服器得通知每個客戶端當前線上

linux c 基於UDP聊天程式

client.c #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<sys/types.h> #

linux c++select聊天程式

比較簡單的多人聊天程式,可直接執行。 主要是實現功能。沒有介面也沒有多餘功能,只是實現群聊天的功能。c/s模式。 server端用select多路複用來做,可以接受多個客戶端連線。client端啟動2個執行緒控制傳送和接受資料。 ======================

Linux C基於UDP的網路程式設計

套接字(socket) socket是一種可以進行網路通訊的核心物件,它有一個唯一的識別符號,一般稱它為socket描述符——sockfd,可類比於檔案描述符fd,基於Linux下一切皆檔案的概念,所以sockfd也可以用read/write/close操作。

c++網路通訊聊天室Server端執行程式碼,及小白的學習情況和經驗總結

c++網路通訊多人聊天室Server端 一、描述 1> 採用c++語言 2>編譯環境是vs2015 3>使用的是阻塞式套接字 二、功能描述 1>一個伺服器對多個客戶端 2>通過廣播的方式使得客戶端與伺服器端都能夠接收到彼此的訊息 3>伺

linux環境下的聊天程式設計

STEP 1:老師給出了原始的程式,是功能不完善的,也就是讓我們把發信息的使用者名稱和時間啥的顯示出來,這樣不是比較合理嘛;原程式是可以實現傳text的,就是沒有使用者名稱而已。 先跑一下(切換到你放這三檔案的目錄哦~):gcc -o chat chat.c 回車 然後:.

一個簡單的基於udp協議的聊天程式

下面,我就介紹一下我開發的一個使用udp協議的網路通訊程式、 程式的要求非常簡單,就是當我們知道對方的ip地址後,我們可以通過命令列輸入對方的ip地址,就可以向對方傳送文字資訊。 程式的使用方式:由命令列開啟程式,命令列有一個可選的引數,即你想要通訊的目標的ip地址(首先要

基於tcp和線程的聊天室-C語言

同時 reat 錯誤 con play 分享圖片 tdi %s 線程編程 之前在學習關於網絡tcp和多線程的編程,學了知識以後不用一下總絕對心虛,於是就編寫了一個基於tcp和多線程的多人聊天室。 具體的實現過程:   服務器端:綁定socket對象->設置監聽數-

Linux基於Socket網絡通信的聊天

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

【tcp-ip學習總結】基於udp聊天室,帶有登入註冊功能

環境;vs2010,vs2013 伺服器端 #include<stdio.h> #include<Winsock2.h> #include<stdlib.h> #pragma comment(lib,"Ws2_32

C#】寫一個支援聊天的TCP程式

碎碎念 先談談我們要實現的效果:客戶端可以選擇要聊天的物件,或者直接廣播訊息(類似QQ的私聊和群訊息) 那麼,該如何實現呢? 首先明確的是,要分客戶端和伺服器端兩個部分(廢話) 客戶端:選擇要傳送的物件,傳送資訊。同時有一個執行緒在監聽是否收到新的資訊。 伺服器端:負責轉發收到的訊息,並負責管理所有接入的連線

c#基於udp實現的p2p語音聊天工具

initial lis combobox pre cat microsoft user eat let 原創性申明 此博文的出處 為?http://blog.csd

基於flask框架,使用websocket實現聊天室功能

後端程式碼:   # web_socket 的收發機制 # web_socket --> web + socket --> http協議 + socket # web_socket協議就是ws協議 # 基於flask框架為web_socket提供服務 from flas

基於C/S模式的簡單聊天程式(伺服器篇)

上篇介紹了客戶端的寫法,這一篇介紹伺服器的寫法。 伺服器的功能是:接收來自客戶端的訊息,然後將訊息轉發給當前連線的所有使用者。這裡一個困擾我許久的地方是如何儲存所有使用者的地址(套接字),找了許久我找到了一種變長陣列的資料結構Vector,用size()來獲取長

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

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

15.基於UDP協議的聊天程式

使用UDP協議完成一個聊天室程式的小專案,大部分程式碼都有註釋,一看就能看到的. 實現的功能:               (1)檢視/顯示已經登陸的使用者資訊               (2)向已登陸的使用者傳送訊息               (3)輸出錯誤訊息,給

linux環境下基於udp socket簡單聊天通訊

客戶端程式碼:client.c /* * File: main.c * Author: guanyy * * Created on 20161202 * * 主要實現:客戶端和服務端相互通訊 */ #include <stdio.h> #i

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

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

使用UDP實現簡單聊天功能

使用UDP實現簡單聊天功能 使用UDP實現一個簡單的多人聊天功能。該程式使用了多執行緒,實現了聊天功能。 package 課後作業.E103_10_聊天; import java.io.IOException; import java.net.*; i

Linux區域網聊天軟體

功能介紹 客戶端:登陸及註冊;列出當前線上使用者列表、傳送聊天訊息、傳輸檔案等。 服務端:記錄註冊及線上使用者連結串列、記錄使用者聊天資料、顯示使用者的登陸退出等。 主要知識點:socket套接字、連結串列使用者管理、執行緒建立管理、IO複用、selec