1. 程式人生 > >基於TCP/IP協議的多執行緒雙向通訊在OpenWrt上的實現

基於TCP/IP協議的多執行緒雙向通訊在OpenWrt上的實現

1、TCP/IP協議組

TCP/IP協議(傳輸控制協議)由網路層的IP協議和傳輸層的TCP協議組成。

  • IP層負責網路主機的定位,資料傳輸的路由,由IP地址可以唯一的確定Internet上的一臺主機。
  • TCP層負責面向應用的可靠的或非可靠的資料傳輸機制,這是網路程式設計的主要物件。

TCP/IP是個協議組,可分為三個層次:網路層、傳輸層和應用層:

  • 網路層:IP協議、ICMP協議、ARP協議、RARP協議和BOOTP協議;
  • 傳輸層:TCP協議與UDP協議;
  • 應用層:FTP、HTTP、TELNET、SMTP、DNS等協議;

這裡寫圖片描述

2、TCP特點:

  • TCP是面向連線的協議,通過三次握手建立連線,通訊完成時要拆除連線,由於TCP是面向連線協議,所以只能用於點對點的通訊。而且建立連線也需要消耗時間和開銷。
  • TCP傳輸資料無大小限制,進行大資料傳輸。
  • TCP是一個可靠的協議,它能保證接收方能夠完整正確地接收到傳送方傳送的全部資料。

TCP是一種面向連線的保證可靠傳輸的協議。通過TCP協議傳輸,得到的是一個順序的無差錯的資料流。傳送方和接收方的成對的兩個socket之間必須建立連線,以便在TCP協議的基礎上進行通訊,當一個socket(通常都是server socket)等待建立連線時,另一個socket可以要求進行連線,一旦這兩個socket連線起來,它們就可以進行雙向資料傳輸,雙方都可以進行傳送或接收操作。

3、HTTP

HTTP協議是建立在TCP協議之上的一種應用,HTTP連線使用的是“請求—響應”的方式,不僅在請求時需要先建立TCP連線,而且需要客戶端向伺服器發出請求後,請求中包含請求方法、URI、協議版本以及相關的MIME樣式的訊息,伺服器端才能回覆資料,包含訊息的協議版本、一個成功和失敗碼以及相關的MIME式樣的訊息。在請求結束後,會主動釋放連線。從建立連線到關閉連線的過程稱為“一次連線”。
由於HTTP在每次請求結束後都會主動釋放連線,因此HTTP連線是一種“短連線”,要保持客戶端程式的線上狀態,需要不斷地向伺服器發起連線請求。通常的做法是即時不需要獲得任何資料,客戶端也保持每隔一段固定的時間向伺服器傳送一次“保持連線”的請求,伺服器在收到該請求後對客戶端進行回覆,表明知道客戶端“線上”。若伺服器長時間無法收到客戶端的請求,則認為客戶端“下線”,若客戶端長時間無法收到伺服器的回覆,則認為網路已經斷開。

結論:HTTP是應用層協議,其傳輸都是被包裝成TCP協議傳輸。可以用SOCKET實現HTTP。SOCKET是實現傳輸層協議的一種程式設計API,可以是TCP,也可以是UDP。

4、Socket

Socket通常也稱作”套接字“,用於描述IP地址和埠,是一個通訊鏈的控制代碼。網路上的兩個程式通過一個雙向的通訊連線實現資料的交換,這個雙向鏈路的一端稱為一個Socket,一個Socket由一個IP地址和一個埠號唯一確定。應用程式通常通過”套接字”向網路發出請求或者應答網路請求。Socket是TCP/IP協議的一個十分流行的程式設計介面,但是,Socket所支援的協議種類也不光TCP/IP一種,因此兩者之間是沒有必然聯絡的。

1、套接字(socket)概念:

套接字(socket)是通訊的基石,是支援TCP/IP協議的網路通訊的基本操作單元。它是網路通訊過程中端點的抽象表示,包含進行網路通訊必須的五種資訊:連線使用的協議,本地主機的IP地址,本地程序的協議埠,遠地主機的IP地址,遠地程序的協議埠。

簡單地說,套接字就是網路程序的ID,網路通訊歸根到底是程序的通訊,在網路中,每個節點有一個網路地址(即IP地址),兩個程序通訊時,首先要確定各自所在網路節點的網路地址,但是,網路地址只能確定程序所在的計算機,而一臺計算機上可能同時有多個網路程序,還不能確定到底是其中的哪個程序,由此套接字中還要有其他的資訊,那就是埠號(Port),在一臺計算機中,一個埠一次只能分配給一個程序,即埠號與程序是一一對應的關係,所以,埠號和網路地址就能唯一地確定Internet中的一個網路程序。可以認為:套接字=網路地址+埠號。

2、Socket通訊過程:

服務端監聽某個埠是否有連線請求,客戶端向服務端傳送連線請求,服務端收到連線請求向客戶端發出接收訊息,這樣一個連線就建立起來了。客戶端和服務端都可以相互發送訊息與對方進行通訊。

3、建立socket連線:

建立Socket連線至少需要一對套接字,其中一個運行於客戶端,稱為ClientSocket ,另一個運行於伺服器端,稱為ServerSocket。

4、套接字之間的連線過程分為三個步驟:伺服器監聽,客戶端請求,連線確認。

  • 伺服器監聽:伺服器端套接字並不定位具體的客戶端套接字,而是處於等待連線的狀態,實時監控網路狀態,等待客戶端的連線請求;
  • 客戶端請求:指客戶端的套接字提出連線請求,要連線的目標是伺服器端的套接字。為此,客戶端的套接字必須首先描述它要連線的伺服器的套接字,指出伺服器端套接字的地址和埠號,然後就向伺服器端套接字提出連線請求。
  • 連線確認:當伺服器端套接字監聽到或者說接收到客戶端套接字的連線請求時,就響應客戶端套接字的請求,建立一個新的執行緒,把伺服器端套接字的描述發給客戶端,一旦客戶端確認了此描述,雙方就正式建立連線。而伺服器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連線請求。

5、一個伺服器如何為多個客戶端併發服務

應用層通過傳輸層進行資料通訊時,TCP會遇到同時為多個應用程式程序提供併發服務的問題。多個TCP連線或多個應用程式程序可能需要通過同一個TCP協議埠傳輸資料。為了區別不同的應用程式程序和連線,許多計算機作業系統為應用程式與TCP/IP協議互動提供了套接字(Socket)介面。應用層可以和傳輸層通過Socket介面,區分來自不同應用程式程序或網路連線的通訊,實現資料傳輸的併發服務。

6、SOCKET連線與TCP連線

  • 建立Socket連線時,可以指定使用的傳輸層協議,Socket可以支援不同的傳輸層協議(TCP或UDP),當使用TCP協議進行連線時,該Socket連線就是一個TCP連線。
  • Socket是應用層與TCP/IP協議族通訊的中間軟體抽象層,它是一組介面。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket介面後面,對使用者來說,一組簡單的介面就是全部,讓Socket去組織資料,以符合指定的協議。

【適用情況】
很多情況下,需要伺服器端主動向客戶端推送資料,保持客戶端與伺服器資料的實時與同步。此時若雙方建立的是Socket連線,伺服器就可以直接將資料傳送給客戶端;

5、多執行緒雙向通訊在OpenWrt上的實現

注意:使用多執行緒連結庫時,OpenWrt的Makefile檔案的編寫注意事項,請參考 此處

有關socket程式設計用到函式請參考 socket

1、TCP程式設計的客戶端一般步驟:

1、建立一個socket,用函式socket();
2、設定socket屬性,用函式setsockopt();* 可選;
3、繫結IP地址、埠等資訊到socket上,用函式bind();* 可選;
4、設定要連線的對方的IP地址和埠等屬性;
5、連線伺服器,用函式connect();
6、收發資料,用函式send()和recv(),或者read()和write();
7、關閉網路連線;

2、TCP程式設計的伺服器端一般步驟:

1、建立一個socket,用函式socket();
2、設定socket屬性,用函式setsockopt(); * 可選;
3、繫結IP地址、埠等資訊到socket上,用函式bind();
4、開啟監聽,用函式listen();
5、接收客戶端上來的連線,用函式accept();
6、收發資料,用函式send()和recv(),或者read()和write();
7、關閉網路連線;
8、關閉監聽;

3、客戶端原始碼(thread_tcpclient.c):
功能介紹:
1、主執行緒裡用於接收伺服器發來的資料,子執行緒 ntid 用於掃描鍵盤輸入,併發送給伺服器端,實現雙向通訊。
2、通過傳送字元 ‘p’ 到伺服器端,伺服器的接收子執行緒返回,並停止伺服器的傳送,進入監聽狀態。

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

#define PORT 8082
#define MAXBUF 512

char send_buf[MAXBUF+1];
void *thread(void *x)  
{  
    int new_fd = *((int*)x);
    while(1)
    {
        bzero(send_buf, MAXBUF + 1);
        scanf("%s",send_buf);
        send(new_fd, send_buf, strlen(send_buf), 0); //第 4 步 向套接字中寫入字串
    }
    return NULL;  
} 

char recv_buf[MAXBUF+1];
int main()
{
   int sockfd=socket(AF_INET,SOCK_STREAM,0);//第 1 步 建立一個體套接字
   struct sockaddr_in svraddr;//第 2 步 設定 addr 結構體
   svraddr.sin_family=AF_INET;//使用 internet 協議
   svraddr.sin_port=htons(PORT);
   inet_aton("192.168.10.1",&svraddr.sin_addr);
   connect(sockfd,(struct sockaddr*)&svraddr,sizeof(svraddr));//第 3 步 連線伺服器

   pthread_t ntid;
   pthread_create(&ntid,NULL,thread,&sockfd);

   while(1)
   {
     bzero(recv_buf, MAXBUF + 1);/* 接收對方發過來的訊息,最多接收 MAXBUF 個位元組 */
     int len = recv(sockfd, recv_buf, MAXBUF, 0);/* 接收伺服器來的訊息 */
     if(len > 0)
        printf("接收訊息成功:'%s',共%d個位元組的資料\n", recv_buf, len);
     else
        printf("訊息接收失敗!錯誤程式碼是%d,錯誤資訊是'%s'\n", errno, strerror(errno));
   }
 /* 關閉連線 */
 close(sockfd);
 return 0;
}

4、伺服器端原始碼(thread_tcpserver.c):

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

#define PORT 8082
#define MAXBUF 512

char recv_buf[MAXBUF+1];
char link_state=1;
void* fun(void* x)
{
   //printf("enter thread!\r\n");
   pthread_detach(pthread_self());//非阻塞
   int new_fd=*((int*)x);
   while(1)
   {
     bzero(recv_buf, MAXBUF + 1);
     int len = recv(new_fd, recv_buf, MAXBUF, 0);
     if(recv_buf[0] == 'p')
     {
        link_state = 0;
        printf("------------客戶端要斷開!伺服器別再發了!----------\r\n");
        break;
     }
   }
   return NULL;
}

char send_buf[MAXBUF+1];
int newfd;
int inewfd=0;
int main()
{
   int sockfd=socket(AF_INET,SOCK_STREAM,0);//第 1 步 建立套接字
   struct sockaddr_in svraddr;//第 2 步 設定地址結構體
   svraddr.sin_family=AF_INET;//使用 internet 協議
   svraddr.sin_port=htons(PORT);
   inet_aton("0.0.0.0",&svraddr.sin_addr);
   int ret=bind(sockfd,(struct sockaddr*)&svraddr,sizeof(svraddr));//第 3 步 繫結
   if(ret<0)
   {
    printf("error bind!\r\n");
    exit(-1);
   }
   listen(sockfd,2);//第 4 步 監聽,最多兩個client
   while(1)
   {
     newfd=accept(sockfd,NULL,NULL); //第 5 步 接收
     pthread_t ntid;
     pthread_create(&ntid,NULL,fun,&newfd); 
     while(1)
     {
        if(link_state == 0)
            break;
        bzero(send_buf, MAXBUF + 1);
        strcpy(send_buf, "hello,my client!\n");
        int len = send(newfd, send_buf, strlen(send_buf), 0);//發訊息給客戶端
        if(len < 0) 
            printf("訊息傳送失敗!錯誤程式碼是%d,錯誤資訊是'%s'\n", errno, strerror(errno));
         else 
            printf("訊息傳送成功,共傳送了%d個位元組!\n", len);
        sleep(1);
     }
     link_state = 1;
   }
 /* 關閉連線 */
 close(sockfd);
 return 0;
}

由於篇幅有限,有關多執行緒的知識將在下次部落格中介紹。

                                                                 @本文作者:LeatherWang

相關推薦

基於TCP/IP協議執行雙向通訊OpenWrt實現

1、TCP/IP協議組 TCP/IP協議(傳輸控制協議)由網路層的IP協議和傳輸層的TCP協議組成。 IP層負責網路主機的定位,資料傳輸的路由,由IP地址可以唯一的確定Internet上的一臺主機。 TCP層負責面向應用的可靠的或非可靠的資料

如何基於TCP/IP協議進行MFC Socket網路通訊程式設計

MFC Socket網路通訊程式設計        最近因為一個專案需要進行區域網絡通訊,向工作單位的軟體工程師請教了一下需要用到哪些知識,然後博主就自學了一遍windows網路通訊程式設計原理,然後就在網上找了一大堆例子,但實際執行效果並不佳,花了大概一週多的時間總算是把

TCP/IP網路程式設計 基於Linux程式設計_4 --執行伺服器端的實現

執行緒基本概念 前面我們講過多程序伺服器,但我們知道它開銷很大,因此我們才引入執行緒,我們可以把它看成是一種輕量級程序。它相比程序有如下幾個優點: 執行緒的建立和上下文切換開銷更小且速度更快。 執行緒間交換資料時無需特殊技術。 程序:在作業系統構成

【Java】基於TCP協議執行伺服器-客戶端互動控制檯聊天室簡例

      前兩天想到一個手機APP專案,使用到藍芽,發現BluetoothSocket和J2EE網路變成的Socket差不多,使用之餘順手寫一個多執行緒伺服器與客戶端互動實現聊天室的一個小例子,方便新人學習網路程式設計模組,期間使用到多執行緒和IO輸入輸出流的

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

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

基於tcp/ip協議,使用socket進行簡單的使用者聊天室

heardfirst裡面有基於tcp/ip協議的socket聊天程式,這裡做一下記錄 SimpleChatClient客戶端類 public class SimpleChatClientA { JTextArea incoimg; JText

基於TCP/IP協議的socket通訊server

while resource err close 通訊 ice inpu utils 緩沖 思路: socket必須要隨項目啟動時啟動,所以需用Spring自帶的監聽器,需要保持長連接,要用死循環,所以必須另外起線程,不能阻礙主線程運行 1.在項目的web.xml中配置li

JAVA——點對面通訊(Socket基於TCP/IP協議

點對面通訊(Socket基於TCP/IP協議) 1.要求 大多情況下,網路通訊經常需要多個客戶機同一個伺服器進行通訊,如FTP伺服器是同時接收多個客戶訪問的伺服器。本例介紹點對面通訊,即一個伺服器監聽多個客戶端的請求的通訊。 2.原理 建立多客戶連線的Soc

基於TCP/IP協議的Socket程式設計

如今的大多數網路通訊都是選擇使用基於TCP/IP的協議進行,其中封裝的比較好的當屬socket了,下面就socket的使用進行詳細的描述: 一、Socket的工作模式 在TCP/IP網路應用中,通訊的兩個程序間相互作用的主要模式是客戶/伺服器(C/S)模式,即客戶向伺服器發

基於socket和執行的聊天程式設計與實現

【要求】 1. 設計一款多人聊天程式,包括伺服器端和客戶端; 2. 伺服器先執行,自動獲取IP,建立socket並繫結在2017埠; 3. 客戶端通過IP地址連線伺服器端,由argv[1]提供IP地址,回車後提示輸入暱稱,然後登入伺服器; 4. 

網絡通信-在瀏覽器輸入url,基於TCP/IP協議的解釋

src url ima 按順序 網絡模型 code initial 技術 不重復 知識點1: 網絡模型 TCP/IP四層 和ISO七層模型 (統一省略後面層字。比如傳輸代表傳輸層) 知識點2: 在應用層中TCP建立連接,經歷的三次握手協議 首先:,TCP協議是什麽? 為

實現基於TCP/IP協議的簡單Client/Server程式

所謂簡單是指的是: 1、伺服器一次只能響應一個客戶端的請求,直到和客戶端斷開連結才可以響應下一個客戶端請求。不能多客戶端連結伺服器 客戶端: 我們是在本機上做的測試,所以客戶端所連結的host地址是用的127.0.0.1這個迴環地址。埠好使用1023以上

基於OkHttp Retrofit RxJava 執行下載。請求、快取、自動更新.限制佇列數.封裝庫

XDownload介紹 本庫封裝基於Okhttp3,Retrofit2,RxJava2.0,Greendao3.2 ps : 當然當然,都封裝好了,你也可以無視 GitHub地址 如果你覺得好用,對你有幫助,請給個star 介面

簡單的 C++ SOCKET程式設計 ---基於TCP/IP協議(轉)

server端: #include <WINSOCK2.H> #include <stdio.h> #pragma comment(lib,"ws2_32.lib") void main() { //建立套接字 WORD myVersion

一份基於quartz的任務執行處理模板

本任務處理模板使用maven管理具體jar包依賴,使用quartz2.2.2搭建的一個定時任務處理模板,模板提供了一個CommonJob類用於quartz呼叫,此類的作用是處理任務模板類,規定了處理任務的步驟為:①獲取待處理任務列表;②遍歷待處理任務列表,逐一進行處理。然後只需要注入一個具體的任務類

Linux C: 基於C/S的執行網路程式設計 2 (客戶端)

客戶端: #include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/type

基於TCP/IP 協議的簡單C/S程式

http://blog.chinaunix.net/uid-23069658-id-3273673.html http://www.oschina.net/code/snippet_153782_16562

基於TCP/IP協議的聊天例項丨首篇介紹及資料包指令碼介紹

首篇介紹 本節包括: 1、資料包指令碼 2、以及對資料包指令碼的測試,檢驗資料包是否能正常工作 聊天例項實現流程:功能及實現流程連結   注:本例項與上鍊接內例項相互獨立,上鍊接為給讀者認識、以及學習TCP/IP提供參考 根據socket通訊基本流程圖

Android端與服務端基於TCP/IP協議的Socket通訊

什麼是TCP/IP協議? 百度百科的解釋:Transmission Control Protocol/Internet Protocol的簡寫,中譯名為傳輸控制協議/因特網互聯協議,又名網路通訊協議,是Internet最基本的協議、Internet國

基於tcp/ip協議的ModBus

一 乙太網的標準   乙太網是一種區域網。早期標準為IEEE 802.3,資料鏈路層使用CSMA/CD,10Mb/s速度物理層有: (1)10 Base 5粗同軸電纜,RG-8,一段最長為500m; (2)10 Base 2細同軸電纜,RG-58,一段最長為185m;