1. 程式人生 > >(二)用多執行緒管理TCP多個客戶端連線伺服器

(二)用多執行緒管理TCP多個客戶端連線伺服器

該程式的服務端大概工作邏輯如左圖: 首先說說這個程式的作用:這個程式可用於多個客戶端通過連線伺服器來互相通訊。如qq群聊。當一個客戶端有資訊發過來後,服務端就會通過客戶端佇列轉發給其他客戶端 先上程式碼:
//TCP服務端
#include"myhead.h"

struct client *head = NULL;
struct sockaddr_in saddr;
struct sockaddr_in caddr;

struct client
{
	int sock;
	struct client *next;
};

struct client *init_list()               //建立客戶端佇列頭,為了讓客戶端“群聊”
{
	struct client *head = malloc(sizeof(struct client));
	head->next = NULL;
	return head;
}

int add_node(struct client*head,int new_sockfd)
{
	struct client *new = malloc(sizeof(struct client));
	struct client *p = head;

	new->sock = new_sockfd;
	new->next = NULL;

	while(p->next!=NULL)
	{
		p = p->next;
	}
	p->next = new;
	new->next = NULL;
	return 0;
}

int del_node(struct client*head,int sockfd)
{
	struct client *q = head;
	struct client *p = q->next;

	while(p->sock !=sockfd)
	{
		if(p->next !=NULL)
		{
			p = p->next;
			q = q->next;
		}
		else if(p->next == NULL)    //cannot find the sockfd
		{
			printf("can not find sockfd to del\n");
			return -1;
		}
	}
	q->next = p->next;
	free(p);
	return 0;
}

int broadcast_client(struct client*head,int sockfd,char *buf)
{
	struct client *p = head->next;
	while(p!=NULL)
	{
		if(p->sock != sockfd)
		{
			write(p->sock,buf,50);
		}
		else if(p->sock == sockfd)
		{
			p = p->next;
			continue;
		}
		p = p->next;
	}
	return 0;
}

void* thread(void* arg)
{
	pthread_detach(pthread_self());              //設定該執行緒為分離狀態,不需要主執行緒回收其系統資源。
	char buf[50];
	char ipbuf[50];
	bzero(ipbuf,50);
	bzero(buf,50);
	int port;
	int sockfd = *((int*)arg);
	while(1)                                     //迴圈接收客戶端發來的資訊
	{
		read(sockfd,buf,50);
		if(strcmp(buf,"quit")==0)            //當客戶端發來的資訊為 quit,則退出執行緒,並刪除該結點
		{
			del_node(head,sockfd);
			pthread_exit(NULL);
		}	
		inet_ntop(AF_INET,(void*)&caddr.sin_addr.s_addr,ipbuf,50);	//把客戶端的ip資訊放到ipbuf中
		port = ntohs(caddr.sin_port);                                   //把客戶端的埠號放到變數port中
		printf("read from ip:%s,port:%hu\n",ipbuf,port);
		printf("message:%s\n",buf);
		broadcast_client(head,sockfd,buf);                              //把一個客戶端發來的資訊轉發給其他客戶端
		bzero(buf,50);
	}
}

int main()
{
	
	int sockfd,new_sockfd;
	int size,ret;
	

	pthread_t tid;

	size = sizeof(struct sockaddr_in);
	head = init_list();

	bzero(&saddr,size);
	saddr.sin_family = AF_INET;                 //繫結協議域為 IPv4
	saddr.sin_port = htons(7777);               //繫結埠號為7777
	saddr.sin_addr.s_addr = htonl(INADDR_ANY);  //繫結ip地址為本機的一個隨機IP

	sockfd = socket(AF_INET,SOCK_STREAM,0);     //建立socket套接字
	ret = bind(sockfd,(struct sockaddr*)&saddr,size);          //socket套接字和sockaddr_in結構體繫結在一起,賦予socket屬性
	listen(sockfd,5);                               //開始監聽有沒有客戶端連線

	while(1)                   //迴圈監聽有沒有客戶端連線進來,就像一個接待人員等待客人,有客人來了就服務他
	{
		new_sockfd = accept(sockfd,(struct sockaddr*)&caddr,&size);      //等待客戶端連線,並返回該客戶端的描述符
		add_node(head,new_sockfd);                                       //若有客戶端連線,則把該客戶端加入到客戶端佇列中

		pthread_create(&tid,NULL,thread,(void*)&new_sockfd);            //建立一個執行緒服務新連線進來的客戶端

	}
	pthread_exit(NULL);
	return 0;
}
接下來是客戶端:
//TCP客戶端
#include"myhead.h"

void* thread(void* arg)             //讀取從伺服器轉發過來的資訊,這些資訊是其他客戶端發到伺服器上,伺服器再轉發過來的
{
	char buf[50];
	int sockfd = *((int*)arg);
	while(1)                      //迴圈等待伺服器有沒有資訊發過來,有就打印出來,沒就阻塞等待
	{
		read(sockfd,buf,50);
		printf("%s\n",buf);
	}
}

int main()
{
	int sockfd;
	int size;
	char buf[50]={0};
	pthread_t tid;
	struct sockaddr_in saddr;
	size = sizeof(saddr);
	bzero(&saddr,size);

	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(7777);
	saddr.sin_addr.s_addr = inet_addr("192.168.152.128");   //這裡的IP是服務端的IP

	sockfd = socket(AF_INET,SOCK_STREAM,0);
	connect(sockfd,(struct sockaddr*)&saddr,size);            //連線服務端

	pthread_create(&tid,NULL,thread,(void*)&sockfd);          //連線成功後,建立一條執行緒用於迴圈讀取服務端發來的資訊
	while(1)                                                  //主執行緒用於給服務端發信息。
	{
		scanf("%s",buf);
		write(sockfd,buf,50);
		bzero(buf,50);
	}
	return 0;
}


相關推薦

執行管理TCP客戶連線伺服器

該程式的服務端大概工作邏輯如左圖: 首先說說這個程式的作用:這個程式可用於多個客戶端通過連線伺服器來互相通訊。如qq群聊。當一個客戶端有資訊發過來後,服務端就會通過客戶端佇列轉發給其他客戶端 先上程式碼: //TCP服務端 #include"myhead.h" struc

C++——執行程式設計std::mutex 執行同步、解決資源競爭問題

前言 執行緒同步 這裡的“同”不是同時、一起執行的意思,而是指協同、協助、互相配合。執行緒同步是指多個執行緒協同步調,按預定的先後次序進行執行。 執行緒A和B一塊配合,A執行到一定程度時要依靠B的某個結果,於是停下來,示意B執行;B依言執行,再將結果給A;

Java核心深入理解執行池ThreadPool

本文你將獲得以下資訊: 執行緒池原始碼解讀 執行緒池執行流程分析 帶返回值的執行緒池實現 延遲執行緒池實現 為了方便讀者理解,本文會由淺入深,先從執行緒池的使用開始再延伸到原始碼解讀和原始碼分析等高階內容,讀者可根據自己的情況自主選擇閱讀順序和需要了解的章節。 一、執行緒池優點

執行執行者建立一個執行執行者

宣告:本文是《 Java 7 Concurrency Cookbook 》的第四章,作者: Javier Fernández González     譯者:許巧輝     校對:方騰飛 建立一個執行緒執行者 使用Executor framework的第一步就是建立一個ThreadPoolEx

EventBus3.0使用總結EventBus的執行模式

在通過指定執行緒模式宣告訂閱方法的時候使用的是ThreadMode.MAIN執行緒模式。 @Subscribe(threadMode = ThreadMode.MAIN) EventBus有4種執行緒模式: ThreadMode: POSTING

執行版本TCP聊天程式服務

   這是一個通過多執行緒來實現可以接受多個客戶端的TCP聊天程式。    //這是一個實現多執行緒TCP的聊天程式服務端 #include<stdio.h> #include<stdlib.h> #includ

Linux c==TCP客戶連線伺服器 (20)

通過父子程序實現TCP的多個客戶端連線伺服器 tcp_sever_fork.c #include <stdio.h> #include <string.h> #i

2017.8.22 python實現簡單基於TCP/IP的客戶伺服器

伺服器端 import socket serversocket=socket.socket(socket.AF_INET,socket.SOCK_STREAM) serversocket.bind((

執行Java執行,啟動四執行,兩執行加一,另外兩執行減一

  public class Test { public static void main(String[] args) { final ShareData data = new ShareData(); for (int i = 0; i < 2; i++) {

nodejs學習筆記——javascript的同步非同步行為和執行

寫過後臺的同學一定對執行緒、執行緒池或者是多執行緒這些概念不會陌生,但是前臺在HTML5之前很少會提及,因為在HTML5之前javascript都是單執行緒的。下面用一個簡單的例子來說明一下單執行緒: setInterval(function(){ var date

FFmpeg總結ffmpeg與nginx實現直播路流並發播放

xxx 開源 conf ref itl rect arc med rtm 圖:撒哈拉沙漠 下載 nginx 和 nginx-rtmp源碼: http://nginx.org/download/nginx-1.5.10.tar.gz https://github.com/a

socket區域網 通過執行Thread將pygame得到的攝像頭影象傳給客戶

該專案是在 https://blog.csdn.net/dss_dssssd/article/details/82848512 專案基礎上新增socket傳輸影象的功能。 這個小專案檔案比較多,就先放在github上了, 專案地址:https://github.com/MengRe/

第一次伺服器專案打包執行

開發環境:IDEA 2018.1 基於SpringBoot 2.0 + Maven1. 首先打包:  在pom.xml中配置: <groupId>自定義</groupId> <artifactId>自定義</artifactId> <

如何實現執行?實現執行為什麼要調start,而不是run方法?繼承Thread類、實現Ruable介面、Callable<V>

什麼是程序? 作業系統中一個程式的執行週期(從開啟到關閉)。程序是具有一個或多個執行緒的執行緒組。 什麼是執行緒? 一個程序可以同時執行多個任務,任務就是執行緒,一個程序至少有一個執行緒。 執行緒執行在程序內部,執行緒是輕量級程序。 程序和執行緒比較:

Java執行 什麼是執行

宣告:本系列大多是翻譯自https://www.javatpoint.com,加上自己的增刪改,盡力寫的系統而通俗易懂,後文不再重複宣告。 java的多執行緒是一個同時執行多個執行緒的過程。 執行緒是一個輕量級的子程序,是最小的處理單元。多執行緒和多程序都用於實現多工處理。 但是,我們使用多執

執行管理使用本地執行變數

宣告:本文是《 Java 7 Concurrency Cookbook 》的第一章, 作者: Javier Fernández González 譯者:鄭玉婷 校對:方騰飛 使用本地執行緒變數 併發應用的一個關鍵地方就是共享資料。這個對那些擴充套件Thread類或者實現Runnable介面的物

Python實戰之執行函式執行,類執行,守護執行,GIL,執行lock,遞迴Rlock,Semaphore訊號量,event

首先須知 什麼是IO? 從硬碟讀塊資料,從網路讀塊資料屬於IO操作(IO操作不佔用cpu) 計算佔用cpu,如:1+1 Python多執行緒其實就是一個執行緒,由於利用CUP的上下文切換看起來就像是併發..上下文切換消耗資源 Python多執行緒 不適合CPU密集操作型的任務,適

執行學習:停止執行

停止執行緒 停止一個執行緒可以使用Thread.stop()方法,但最好不用它,因為這個方法是不安全的,而且已被棄用。 大多數停止一個執行緒的操作使用Thread.interrupt()方法,但是這個方法不會終止一個正在執行的執行緒,還需要加入一個判斷才可以完成執行緒的停止。 Jav

如何實現執行?實現執行為什麼要調start,而不是run方法?繼承Thread類、實現Ruable介面、Callable

什麼是程序? 作業系統中一個程式的執行週期(從開啟到關閉)。程序是具有一個或多個執行緒的執行緒組。 什麼是執行緒? 一個程序可以同時執行多個任務,任務就是執行緒,一個程序至少有一個執行緒。 執行緒執行在程序內部,執行緒是輕量級程序。 程序和執行緒比較: 與

java執行:ExecutorService執行例項

瞭解了ExecutorService,現在就來看下具體業務的具體應用。 解決大量資料同時插入資料庫的多執行緒實現,解決其效能問題: 1、執行緒池 package com.akk.thread; import java.util.ArrayList; import java