1. 程式人生 > >linux基礎程式設計 套接字socket 完整的伺服器端多執行緒socket程式

linux基礎程式設計 套接字socket 完整的伺服器端多執行緒socket程式

此段程式來自我的一個專案中,稍微做了些修改,執行穩定,客戶端程式比較簡單所以未編寫,可以用socket除錯工具測試此段程式碼

費話不多說,直接上程式碼

#include<stdlib.h> 
#include<stdio.h> 
#include<string.h> 
#include<errno.h> 
#include<netdb.h> 
#include<sys/types.h> 
#include<netinet/in.h> 
#include<sys/socket.h> 
#include<sys/wait.h> 
#include<unistd.h> 
#include<pthread.h> 
#include<fcntl.h>

#define __DEBUG
#ifdef __DEBUG
#define DBG(fmt,args...) fprintf(stdout,  fmt,  ##args)
#else
#define DBG(fmt,args...)
#endif
#define ERR(fmt,args...) fprintf(stderr,  fmt,  ##args)

/*
isStreamQuit == 0 :Start
isStreamQuit == 1 :Client Quit
isStreamQuit ==-1 :App Quit
*/
static int isStreamQuit    = 0;
static int gStreamServerFd = -1;
int gStreamClientFd;

#define PORT_SOCKET          9000	//server監聽埠
#define RECV_BUF_MAX_LEN     512
#define TIME_WAIT            200000		/*200ms*/

/*
socket傳送函式
 */
int ScketSend(unsigned char *buf,unsigned int len)
{
	
	int ret = 0;
	if(gStreamClientFd <= 0)
		return -1;
	ret = send(gStreamClientFd,buf,len,0);
	if(ret <= 0 ){
		return -1;
	}else if(ret == len){
		return 0;
	}
	while(ret < len){
		ret += send(gStreamClientFd,buf+ret,len-ret,0);
	}
	return 0;
}

/*
socket連線執行緒,阻塞等待客戶端的連線,
連線後迴圈處理客戶端發來的資料,
這裡只能連線一個客戶端,稍加修改,就可以支援多客戶端連線
*/
void *SocketThread(void *arg)
{
	fd_set SockRead;
	struct timeval TimeOut;
	int ret;
	struct sockaddr clientAddr; 
	unsigned char *rcvBuf = (unsigned char *)malloc(RECV_BUF_MAX_LEN);
	
	socklen_t  len;
	len = sizeof(clientAddr);
	while(1){
		
		int rcvLen;
		/*阻塞等待客戶端連線*/
		gStreamClientFd = accept(gStreamServerFd, &clientAddr, &len);
		if(gStreamClientFd == -1){
			ERR("ERROR in stream accept: %s\n",strerror(errno));
			/*add errno handler here,in some case,the error is not fatal*/
			/*code here*/
			break;
		}
		/*isStreamQuit == -1,is the siganl to quit*/
		if(isStreamQuit != -1){
			isStreamQuit = 0;
		}
		DBG("accep a stream client\n");
		/*客戶端已連線,迴圈處理*/
		while(isStreamQuit==0){
			FD_ZERO(&SockRead);
			FD_SET(gStreamClientFd,&SockRead);
			TimeOut.tv_sec = 0;
			TimeOut.tv_usec = TIME_WAIT;
			/*
			200ms超時判斷是否有資料接收,有則接收,沒有繼續迴圈,
			總是讓程式不能一直阻塞在這裡
			*/
			ret = select(gStreamClientFd+1,&SockRead,NULL,NULL,&TimeOut);
			if(ret == -1){
				ERR("ERROR in select\n");
				break;
			}else if(ret == 0){
				continue;
			}
			/*接收客戶端發來的資料*/
			rcvLen = recv(gStreamClientFd,rcvBuf,RECV_BUF_MAX_LEN,0);
			if(rcvLen < 0){
				ERR("ERROR in stream accept: %s\n",strerror(errno));
				/*add errno handler here,in some case,the error is not fatal*/
				/*code here*/
				isStreamQuit = 1;
				break;
			}else if(rcvLen == 0){
				DBG("stream client close\n");
				/*code here*/
				isStreamQuit = 1;
				break;
			}
			DBG("rcvLen: %d,rcvBuf: %s\n",rcvLen,rcvBuf);

			memset(rcvBuf,0,RECV_BUF_MAX_LEN);
		}
		DBG("Close Stream Socket\n");
		close(gStreamClientFd);
		
		/*OTHER Error or App Quit*/
		if(isStreamQuit == -1){
			break;
		}

	}
	DBG("SocketThread exit\n");
	free(rcvBuf);
	close(gStreamServerFd);
	pthread_exit(NULL);
}

/*
socket連線初始化
*/
int SocketInit()
{
	struct sockaddr_in server;
	pthread_t tStreamSocketThr;
	/*建立socket*/
	gStreamServerFd = socket(AF_INET,SOCK_STREAM,0); 
	if(gStreamServerFd == -1 ){
		ERR("ERROR in create Stream Socket!\n");
		return -1;
	}
	memset(&server,0,sizeof(server));
	server.sin_family = AF_INET;
	server.sin_port = htons(PORT_SOCKET);
	server.sin_addr.s_addr = htonl(INADDR_ANY);
	/*繫結監聽埠*/
	if(bind(gStreamServerFd ,(struct sockaddr*)&server,sizeof(server))== -1){
		ERR("ERROR in bind Stream Socket: %s\n",strerror(errno));
		return -1;
	}
	/*開始監聽*/
	if(	listen(gStreamServerFd, 5) == -1){
		ERR("ERROR in listen Stream Socket: %s\n",strerror(errno));
		return -1;
	}
	/*建立socket連線執行緒,用來處理監聽的結果,比如有客戶端連線等*/
	pthread_create(&tStreamSocketThr,NULL,SocketThread,NULL);
	/*release thread resource,so we not use pthread_join to waitting*/
	pthread_detach(tStreamSocketThr);
	return 0;
}

#if 1
int main()
{
	if(SocketInit() == -1){
		return -1;
	}
	while(1){
		sleep(2);
	}
	
	/*notice to exit*/
	isStreamQuit = -1;
	sleep(1);
	if(gStreamServerFd){
		close(gStreamServerFd);
	}
	DBG("SUCCESS in ConnectManageExit\n");
}
#endif 

執行結果
[[email protected] src]# ./socket_connect
accep a stream client
rcvLen: 7,rcvBuf: helle 1
Close Stream Socket
accep a stream client
rcvLen: 7,rcvBuf: hello 2
Close Stream Socket
accep a stream client
rcvLen: 7,rcvBuf: hello 3
rcvLen: 7,rcvBuf: hello 4
rcvLen: 7,rcvBuf: helle 5
Close Stream Socket


相關推薦

linux基礎程式設計 socket 完整伺服器執行socket程式

此段程式來自我的一個專案中,稍微做了些修改,執行穩定,客戶端程式比較簡單所以未編寫,可以用socket除錯工具測試此段程式碼 費話不多說,直接上程式碼 #include<stdlib.h> #include<stdio.h> #include&

基於Socket的服務執行模式——服務和客戶程式碼

本文程式碼來源於《實戰java高併發程式設計》葛一鳴 郭超 著 學習這本書的過程中,感覺這一部分比較重要,自己做下總結,也希望能給大家提供些幫助。       本程式碼模擬簡單的Echo伺服器,對於Echo伺服器,他會讀取客戶端的一個輸入,並將這個輸入原

嵌入式Linux網路程式設計,網路基礎socket(SOCK_STREAM、SOCK_DGRAM、SOCK_RAW),IP地址,埠號,位元組序,位元組序轉換函式,IP地址的轉換

文章目錄 1,socket 1.1,socket的型別(SOCK_STREAM、SOCK_DGRAM、SOCK_RAW) 1.2,socket的位置 2,IP地址 2.1,特殊IP地址: 3,埠號

socket程式設計 程式設計 (純理論,以後補一下實現程式碼)

基本概念   套接字——應用層和傳輸層之間,提供應用傳輸介面 Web/RPC/中介軟體——應用層之上的網路開發 應用程式設計介面API(application programming interface) 套接字介面(socket interface)簡稱套接字,

socket程式設計 程式設計

基本概念 套接字——應用層和傳輸層之間,提供應用傳輸介面 Web/RPC/中介軟體——應用層之上的網路開發 應用程式設計介面API(application programming interface) 套接字介面(socket interface)簡稱套接字,

走進Linux核心網路 的祕密—socket與sock

雙十一 今天是雙十一,記得還在念書的時候,每次都會參加京東圖書滿200-100的活動,然後腦子一熱屯一堆書。印象中人文類的書基本都會看,而電子資訊類的可能就只看了一半,甚至買過哪些都忘了。究其原因,主要是人文類的通常都是自己想看的,而技術類的就跟風看哪個銷量大買

網路程式設計(Socket)

網路預備知識學習:https://blog.csdn.net/hansionz/article/details/85224786 網路程式設計套接字 一.IP地址和埠號 1.IP地址 2.埠號 2.1 什麼是埠號

Linux IPv6 UDP程式設計示例

     udp ipv6套接字程式設計和ipv4介面類似,引數略有不同,流程都包括建立套接字、繫結地址、傳送等。 下面是一個udp ipv6 demo, 包括建立ipv6套接字、繫結地址和傳送資料等。 首先先在linux上配置一個本地站點地址,然後使用這個地址傳送。

linux sock_raw原始程式設計 (轉)和Linux下Libpcap原始碼分析和包過濾機制

sock_raw原始套接字程式設計可以接收到本機網絡卡上的資料幀或者資料包,對與監聽網路的流量和分析是很有作用的.一共可以有3種方式建立這種 socket 1.socket(AF_INET, SOCK_RAW, IPPROTO_TCP|IPPROTO_UDP|IPPROT

網路程式設計基礎 & 基本TCP程式設計-基本函式

套接字基礎 一個通用套接字地址結構sockaddr: struct sockaddr { unsigned short sa_family; //套接字的協議簇地址型別,AF_XX char sa_data[14];//儲存

網路程式設計socket

在學習Linux系統程式設計的時候,程序間的通訊方式包括——管道、訊息佇列、共享記憶體、訊號量等方式。但是這些通訊方式都村子一定的缺陷——都是在同一個機器上的程序間的通訊。為了讓不同機器上的程序之間相互通訊,Linux網路程式設計便可解決。linux系統支援套接字介面,可以通

Socket()在服務器和客戶之間的基本工作原理

SocketSocket之間的連接過程主要可以概括為以下三步: 服務器建立監聽:客戶端初始化Socket動態庫後創建套接字,然後指定客戶端Socket的地址,循環綁定Socket直至成功,然後開始建立監聽,此時客戶端處於等待狀態,實時監控網絡狀態; 客戶端提出請求:客戶端的Socket向服務器端提出

Visual C++網路程式設計經典案例詳解 第3章 執行與非同步程式設計 實現執行同步 互斥物件 使用API函式操作互斥物件

互斥物件和臨界區物件和事件物件作用一樣 用於實現執行緒同步 互斥物件可以線上程中使用 CreateMutex()建立並返回互斥物件 原型如下 HANDLE CreateMutex(   LPSECURITY_ATTIRIBUTES lpMutexAttributes,  

Visual C++網路程式設計經典案例詳解 第3章 執行與非同步程式設計 實現執行同步 互斥物件 程式的唯一執行

互斥物件可在程序中使用 使用者在程序建立互斥物件實現程式例項唯一執行 建立控制檯工程 #include<windows.h>                                //包含標頭檔案 #include<stdio.h> in

Linux】網路

    socket  程序間通訊    ipv4:32位 ipv6:128位 網路位元組序     1.傳送主機通常傳送緩衝區中的資料按照記憶體地址從低到高的順序發出;     2.接收主機把從網路上接到的位元組依次儲存在接收緩衝區中,也是按記憶體地址從低到高的順序儲存;

Visual C++網路程式設計經典案例詳解 第3章 執行與非同步程式設計 程序間通訊 命名管道 命名管道例項

vc新增控制檯工程 名字命名管道例項 新增原始檔 名字 伺服器 #include<windows.h>                                //包含標頭檔案 #include<stdio.h> int main() {  

網路程式設計、網路位元組序及用udp寫客戶和服務聊天程式

認識IP地址 IP協議有兩個版本:IPV4和IPV6。 IPV4:IPV4版本的IP地址是4位元組無符號整數。那麼就存在IP地址資源匱乏的時候,這時可以採用兩種方法: DHCP:ip地址動態分配(應用層協議); NAT: 地址替換; 但是這兩種方法只是暫時的有I

linux網路通訊-

socket程式設計是網路常用的程式設計,我們通過在網路中建立socket關鍵字來實現網路間的通訊。 1.TCP/IP協議 先來簡單瞭解一下TCP/IP協議: iso7層架構 應用層 應用層不僅要提供應用程序所需要資訊交換和遠端操作,而且還要作為應用程序

易學筆記-第1章:socket/1.1 服務socket/1.1.2 sockaddr_in:地址族結構體

易學筆記 十年IT經驗個人學習筆記分享: 開發語言:C/C++/JAVA/PYTHON/GO/JSP WEB架構:Servlets/springMVC/springBoot/springClound 容器架構:Docker容器/Docker叢集/Docker與微服務整合/

易學筆記-第1章:socket/1.1 服務socket/1.1.3 位元組序

易學筆記 十年IT經驗個人學習筆記分享: 開發語言:C/C++/JAVA/PYTHON/GO/JSP WEB架構:Servlets/springMVC/springBoot/springClound 容器架構:Docker容器/Docker叢集/Docker與微服務整合/