1. 程式人生 > >Windows下基於socket多執行緒併發通訊的實現

Windows下基於socket多執行緒併發通訊的實現

    本文介紹了在Windows 作業系統下基於TCP/IP 協議Socket 套介面的通訊機制以及多執行緒程式設計知識與技巧,並給出多執行緒方式實現多使用者與服務端(C/S)併發通訊模型的詳細演算法,最後展現了用C++編寫的多使用者與伺服器通訊的應用例項並附有程式。

關鍵詞:Windows;套接字;多執行緒;併發伺服器;

    Socket 是建立在傳輸層協議(主要是TCP 和UDP)上的一種套接字規範,最初由美國加州Berkley 大學提出,為UNIX 系統開發的網路通訊介面,它定義了兩臺計算機之間通訊的規範,socket 遮蔽了底層通訊軟體和具體作業系統的差異,使得任何兩臺安裝了TCP 協議軟體和實現了Socket 規範的計算機之間的通訊成為可能,Socket 介面是TCP/IP 網路最為通用的應用介面,也是在Internet 上進行網路程式應用開發最通用的API[1],本文介紹了Socket通訊的基本機制以及採用多執行緒技術實現併發通訊的基本原理,並給出例項。

//-----------------------------------------------------------------------------------
// 版權歸scut4009所有
//-----------------------------------------------------------------------------------
// 檔名:SocketSever.cpp
// 編寫人:ZP1015
// 編寫時間:2015/04/7
// 編譯工具: Visual Studio 2008
// 程式說明: socket多執行緒通訊,伺服器端,基於TCP
//------------------------------------------------------------------------------------
#include "stdafx.h"
#include "Socket.h"
#include<windows.h>

HANDLE hMutex;
//------------------------------------------------------------------------------------
//函式名稱:      Send(SOCKET sockClient)
/*函式功能:      傳送資料
/*入口引數:      SOCKET sockClient				 
//出口引數:     
//全域性變數引用:  
//呼叫模組:      無 
//------------------------------------------------------------------------------------*/
void Send(SOCKET sockClient)
{
	char sendBuf[MaxSize];
	int byte = 0;

	while(1)
	{
		WaitForSingleObject(hMutex, INFINITE);
		gets(sendBuf);
		byte= send(sockClient,sendBuf,strlen(sendBuf)+1,0);;//伺服器從客戶端接受資料
		if (byte<=0)
		{
			break;
		}	
		
		Sleep(1000);
		ReleaseMutex(hMutex);

	}
	closesocket(sockClient);//關閉socket,一次通訊完畢
}
//------------------------------------------------------------------------------------
//函式名稱:     Rec()
/*函式功能:     接收函式
/*入口引數:     SOCKET sockClient			 
//出口引數:     
//全域性變數引用:  
//呼叫模組:      無 
//------------------------------------------------------------------------------------*/
void Rec(SOCKET sockClient)
{
	char revBuf[MaxSize];
	int byte = 0;

	while(1)
	{
		WaitForSingleObject(hMutex, INFINITE);

		byte= recv(sockClient,revBuf,strlen(revBuf)+1,0);//伺服器從客戶端接受資料
		if (byte<=0)
		{
			break;
		}	

		printf("%s\n",revBuf);

		Sleep(1000);
		ReleaseMutex(hMutex);

	}
	closesocket(sockClient);//關閉socket,一次通訊完畢
}


//********************************************************************************************************/
//** 函式名 ** main()
//**  輸入  ** 無
//**  輸出  ** 無
//**函式描述** 主函式
//********************************************************************************************************/
int main()
{

	SOCKADDR_IN addrServer;
	int sockServer; 

	
 	if (SOCKET_ERROR ==SocketInit())
 	{
 		return -1;
 	}
	
	addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);		//htol將主機位元組序long型轉換為網路位元組序
	addrServer.sin_family=AF_INET;
	addrServer.sin_port=htons(6666);						//htos用來將埠轉換成字元,1024以上的數字即可
	
	
	sockServer=socket(AF_INET,SOCK_STREAM,0);				//面向連線的可靠性服務SOCK_STRAM
	bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));//將socket繫結到相應地址和埠上
	listen(sockServer,5);									//等待佇列中的最大長度為5

	printf("Welcome,the Host %s is running!Now Wating for someone comes in!\n",inet_ntoa(addrServer.sin_addr));


	int len=sizeof(SOCKADDR);

	SOCKADDR_IN addrClient;

	while(1)			
	{
		SOCKET sockClient=accept(sockServer,(SOCKADDR*)&addrClient,&len);//阻塞呼叫程序直至新的連接出現

		if(sockClient == INVALID_SOCKET)
		{	
			printf("Accept Failed!\n");
			continue; //繼續監聽
		}
		HANDLE hThread1 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Send,(LPVOID)sockClient,0,0);//傳送

		if(hThread1!=NULL)
		{
			CloseHandle(hThread1);
		}
		HANDLE hThread2 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Rec,(LPVOID)sockClient,0,0);//接收

		if(hThread2!=NULL)
		{
			CloseHandle(hThread2);
		}
		Sleep(1000);	//一定要
	}

	getchar();
	return 0;
}
//-----------------------------------------------------------------------------------
// 版權歸scut4009所有
//-----------------------------------------------------------------------------------
// 檔名:SocketClient.cpp
// 編寫人:ZP1015
// 編寫時間:2015/04/7
// 編譯工具: Visual Studio 2008
// 程式說明: socket多執行緒通訊
//------------------------------------------------------------------------------------
#include "stdafx.h"
#include "Socket.h"

#pragma comment(lib,"WS2_32.LIB")

const char *SeverIp = "192.168.1.100";
HANDLE hMutex;

//------------------------------------------------------------------------------------
//函式名稱:      Send(SOCKET sockClient)
/*函式功能:      傳送資料
/*入口引數:      SOCKET sockClient				 
//出口引數:     
//全域性變數引用:  
//呼叫模組:      無 
//------------------------------------------------------------------------------------*/
void Send(SOCKET sockClient)
{
	char sendBuf[MaxSize];
	int byte = 0;

	while(1)
	{
		WaitForSingleObject(hMutex, INFINITE);
		gets(sendBuf);
		byte= send(sockClient,sendBuf,strlen(sendBuf)+1,0);;//伺服器從客戶端接受資料
		if (byte<=0)
		{
			break;
		}	
		
		Sleep(1000);
		ReleaseMutex(hMutex);

	}
	closesocket(sockClient);//關閉socket,一次通訊完畢
}
//------------------------------------------------------------------------------------
//函式名稱:     Rec()
/*函式功能:     接收函式
/*入口引數:     SOCKET sockClient			 
//出口引數:     
//全域性變數引用:  
//呼叫模組:      無 
//------------------------------------------------------------------------------------*/
void Rec(SOCKET sockClient)
{
	
	char revBuf[MaxSize];
	int byte = 0;

	while(1)
	{
		WaitForSingleObject(hMutex, INFINITE);

		byte= recv(sockClient,revBuf,strlen(revBuf)+1,0);//伺服器從客戶端接受資料
		if (byte<=0)
		{
			break;
		}	

		printf("%s\n",revBuf);

		Sleep(1000);
		ReleaseMutex(hMutex);

	}
	closesocket(sockClient);//關閉socket,一次通訊完畢
}

int main()
{
	
	if (SOCKET_ERROR ==SocketInit())
	{
		return -1;
	}

	while(1)
	{
		SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
		SOCKADDR_IN addrSrv;
		addrSrv.sin_addr.S_un.S_addr=inet_addr(SeverIp);//設定需要連線的伺服器的ip地址
		addrSrv.sin_family=AF_INET;
		addrSrv.sin_port=htons(6666);//設定需要連線的伺服器的埠地址
		connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//與伺服器進行連線

		
		HANDLE hThread1 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Rec,(LPVOID)sockClient,0,0);

		if(hThread1!=NULL)
		{
			CloseHandle(hThread1);
		}

		HANDLE hThread2 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Send,(LPVOID)sockClient,0,0);

		if(hThread2!=NULL)
		{
			CloseHandle(hThread2);
		}

		Sleep(1000);
		
	}
	getchar();

    WSACleanup();
	return -1;
}



相關推薦

Windows基於socket執行併發通訊實現

    本文介紹了在Windows 作業系統下基於TCP/IP 協議Socket 套介面的通訊機制以及多執行緒程式設計知識與技巧,並給出多執行緒方式實現多使用者與服務端(C/S)併發通訊模型的詳細演算法,最後展現了用C++編寫的多使用者與伺服器通訊的應用例項並附有程式。 關

windowsLibevent的執行封裝(以檔案傳輸為例)

1、主執行緒負責監聽,子執行緒負責響應連線,同時每個子執行緒增加了連結串列來管理連線進來的客戶端,將上一節中的記憶體管理類也封裝進去。總體框架是不變的。 2、封裝類的實現: #pragma once #include "winsock2.h" #include "event2/liste

windowsPHP Pthreads執行安裝與配置

一、phpinfo()檢視已安裝php版本是否執行緒安全及編譯器版本 ThreadSafety項enabled表示執行緒安全 Compiler項表示編譯器 二、根據以上資訊及系統版本選擇pthreads版本 pthreads下載地址:http://windows.php.n

VS2015 C++ main()進行SOCKET執行網路通訊簡單例子(聊天軟體的搭建)

//伺服器 #include<iostream> #include <Winsock2.h> using namespace std; #pragma comment(lib, "ws2_32.lib") int main() { WSADAT

boost中asio網路庫執行併發處理實現,以及asio在執行模型中執行的排程情況和執行安全。

1、實現多執行緒方法: 其實就是多個執行緒同時呼叫io_service::run         for (int i = 0; i != m_nThreads; ++i)         {             boost::shared_ptr<boost::

基於非阻塞socket執行伺服器的實現------一個伺服器如何與個客戶端進行通訊

      我們首先來看服務端(涉及非阻塞socket和多執行緒): #include <stdio.h> #include <winsock2.h> #include <windows.h> #pragma comment(li

執行併發的單例模式實現

1.1 天生執行緒安全的餓漢式單例 1.2 懶漢式單例 1.2.1 執行緒不安全的懶漢式單例 1.2.2 執行緒安全的懶漢式單例

linux 基於特定通訊協議利用執行同步通訊機制實現的串列埠通訊

</pre><pre name="code" class="cpp">/** *@Title:利用多執行緒同步通訊機制實現串列埠通訊 *@Introduce:主要完成根據特定的通訊協議實現串列埠與PC上特定串列埠 * 通訊軟體的通訊。測試版,只

Socket網路程式設計:基於TCP執行通訊

第一步:編寫啟動服務端的執行緒類 package socket; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.

基於Windows執行UDP通訊(VS2010)

    由於各種原因,需要在Windows下面實現一個關於UDP通訊的模組,使用執行緒去處理資料接收和傳送的功能。 main.cpp 1 2 3 4

dubbo協議的單一長連線與執行併發如何協同工作

開發十年,就只剩下這套架構體系了! >>>   

【小家Java】Future、FutureTask、CompletionService、CompletableFuture解決執行併發中歸集問題的效率對比

相關閱讀 【小家java】java5新特性(簡述十大新特性) 重要一躍 【小家java】java6新特性(簡述十大新特性) 雞肋升級 【小家java】java7新特性(簡述八大新特性) 不溫不火 【小家java】java8新特性(簡述十大新特性) 飽受讚譽 【小家java】java9

linuxC開發執行程式

轉:https://blog.csdn.net/lingfemg721/article/details/6574804   linux下用C開發多執行緒程式,Linux系統下的多執行緒遵循POSIX執行緒介面,稱為pthread。   #

java併發程式設計一一執行之間通訊(一)

1.多執行緒之間如何實現通訊 多執行緒之間通訊,其實就是多個執行緒在操作同一個資源,但是操作的動作不同。 1.1什麼是多執行緒之間通訊? 需求:第一個執行緒寫入(input)使用者,另一個執行緒讀取(out)使用者。實現讀一個,寫一個操作。 1.2多執行緒之間通訊需求?

面試題之——執行併發面試題

1) 什麼是執行緒?   執行緒是作業系統能夠進行運算排程的最小單位,它被包含在程序之中,是程序中的實際運作單位。程式設計師可以通過它進行多處理器程式設計,你可以使用多執行緒對運算密集型任務提速。比如,如果一個執行緒完成一個任務要100毫秒,那麼用十個執行緒完成改任務只需10毫秒。Java在語言層面對多執行

網際網路架構執行併發程式設計高階教程(上)

#基礎篇幅:執行緒基礎知識、併發安全性、JDK鎖相關知識、執行緒間的通訊機制、JDK提供的原子類、併發容器、執行緒池相關知識點  #高階篇幅:ReentrantLock原始碼分析、對比兩者原始碼,更加深入理解讀寫鎖,JAVA記憶體模型、先行發生原則、指令重排序 #環境說明:idea、ja

實驗5 結果不唯一的執行併發執行例項 操作指導

實驗5  結果不唯一的多執行緒併發執行例項 操作指導 變數及函式說明   pthread_t 型別定義:typedef unsigned long int pthread_t; //come from /usr/include/bits/

JAVA學習筆記(併發程式設計 - 玖)- 執行併發拓展

文章目錄 死鎖 概念 產生條件 例子 併發最佳實踐 Spring與執行緒安全 死鎖 概念 死鎖是指兩個或兩個以上的程序在執行過程中,由於競爭資源或者由於彼此通訊而造成的一種阻塞的現象

Jmeter測試執行併發請求 與 OSS 物件儲存 測試報告

  1.測試資料夾包含特殊字元 出現重大BUG問題:  \\ 和 /  運用到Key中  資料夾不能刪除 解決方案:應該在根源上傳之前進行   規避  出現這樣的字元在一起 直接丟擲錯誤資訊給使用者 2.測

Java執行-併發執行

執行緒池有了解嗎? 答: java.util.concurrent.ThreadPoolExecutor 類就是一個執行緒池。客戶端呼叫ThreadPoolExecutor.submit(Runnable task) 提交任務,執行緒池內部維護的工作者執行緒的數量就是該執行緒池的執行