日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

【学习笔记】在windows下进行基于TCP的本地客户端和服务端socket通信

發布時間:2024/9/30 windows 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【学习笔记】在windows下进行基于TCP的本地客户端和服务端socket通信 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • socket介紹
    • java中使用socket
    • 基于tcp的socket通信
      • 使用ServerSocket類創建一個web服務器:(java)
    • windows下的基于tcp的socket編程(c++寫)
    • InetAddress 類的方法
    • 附錄1 TCP UDP
    • 附錄2 websocket



socket介紹

Socket的英文原義是“孔”或“插座”。在編程中,Socket被稱做 套接字,是網絡通信中的一種約定。
Socket編程用于解決我們 客戶端與 服務端之間通信的問題。
套接字使用TCP提供了兩臺計算機之間的通信機制。 客戶端程序創建一個套接字,并嘗試連接服務器的套接字。

當連接建立時,服務器會創建一個 Socket 對象。客戶端和服務器現在可以通過對 Socket 對象的寫入和讀取來進行通信。

java.net.Socket 類代表一個套接字,并且java.net.ServerSocket 類為服務器程序提供了一種來監聽客戶端,并與他們建立連接的機制。
TCP 是一個雙向的通信協議,因此數據可以通過兩個數據流在同一時間發送
java中的serversocket類:用于創建Socket套接字的服務端,而Socket類的作用是創建Socket的客戶端。代碼層面是用Socket類去連接ServerSocket類,即客戶端主動連接服務端。
每一個socket都有一個輸出流和一個輸入流,客戶端的輸出流連接到服務器端的輸入流,而客戶端的輸入流連接到服務器端的輸出流。

例:

java中使用socket

服務端:

public static void main(String[]args){try{ServerSocket socket = new ServerSocket(8088);System.out.println("阻塞開始:"+System.currentTimeMillis());socket.accept();System.out.println("server阻塞結束:"+System.currentTimeMillis());socket.close();} catch (IOException e) {e.printStackTrace();}}

現在寫客戶端:

public static void main(String[]args){try {System.out.println("client連接準備"+System.currentTimeMillis());Socket socket = new Socket("localhost",8088);System.out.println("連接結束:"+System.currentTimeMillis());socket.close();}catch (UnknownHostException e){e.printStackTrace();}catch (IOException E){E.printStackTrace();}}


(只有啟動客戶端時才輸出阻塞結束的一行,當不啟動時保持阻塞狀態)
new Socket(“www.csdn.net”,80);可以把參數寫成其他IP地址或者域名,如果寫成域名,就會使用DNS服務轉成IP地址再訪問服務端。

public static void main(String[]args) throws IOException {Socket socket = null;try {System.out.println("client連接準備");socket = new Socket("www.csdn.net",80);System.out.println("連接成功:");}catch (IOException e){e.printStackTrace();}finally {socket.close();}}

基于tcp的socket通信

TCP提供基于“流”的“長連接”的數據傳遞,發送的數據帶有順序性。TCP是一種流協議,以流為單位進行數據傳輸。
什么是長連接?長連接可以實現當服務端與客戶端連接成功后連續地傳輸數據,在這個過程中,連接保持開啟的狀態,數據傳輸完畢后連接不關閉。長連接是指建立Socket連接后,無論是否使用這個連接,該連接都保持連接的狀態。
什么是短連接?短連接是當服務端與客戶端連接成功后開始傳輸數據,數據傳輸完畢后則連接立即關閉,如果還想再次傳輸數據,則需要再創建新的連接進行數據傳輸。
如何建立連接呢?需要客戶端與服務端進行三次握手,握手成功后說明客戶端與服務端能實現數據通信。UDP是無連接協議,也就是客戶端與服務端沒有確認彼此都存在的握手過程,因此不存在長連接與短鏈接概念。

1)長連接的優缺點
1)優點:除了第一次之外,客戶端不需要每次傳輸數據時都先與服務端進行握手,這樣就減少了握手確認的時間,直接傳輸數據,提高程序運行效率。
2)缺點:在服務端保存多個Socket對象,大量占用服務器資源。
(2)短連接的優缺點
1)優點:在服務端不需要保存多個Socket對象,降低內存占用率。
2)缺點:每次傳輸數據前都要重新創建連接,也就是每次都要進行3次握手,增加處理的時間。

使用ServerSocket類創建一個web服務器:(java)

public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(6666);Socket socket = serverSocket.accept();InputStream inputStream = socket.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String getString = "";while (!"".equals(getString = bufferedReader.readLine())) {System.out.println(getString);}OutputStream outputStream = socket.getOutputStream();outputStream.write("HTTP/1.1 200 OK\r\n\r\n".getBytes());outputStream.write("<html><body>< a href=' '>i am baidu.com welcome you!</a></body></html>".getBytes());outputStream.flush();inputStream.close();outputStream.close();socket.close();serverSocket.close();}

(這是書上的代碼,很奇怪打開瀏覽器后打不開)

windows下的基于tcp的socket編程(c++寫)

本地TCP客戶端往本地TCP服務端發送數據,TCP服務端收到數據則會打印輸出,同時把原數據返回給TCP客戶端。這個例子類似于我們在做單片機的串口實驗時,串口上位機往我們的單片機發送數據,單片機收到數據則把該數據原樣返回給上位機。

tcp_server.c:

#include <stdio.h> #include <winsock2.h>#define BUF_LEN 100int main(void) {WSADATA wd;SOCKET ServerSock, ClientSock;char Buf[BUF_LEN] = {0};SOCKADDR ClientAddr;SOCKADDR_IN ServerSockAddr;int addr_size = 0, recv_len = 0;/* 初始化操作sock需要的DLL */WSAStartup(MAKEWORD(2,2),&wd); /* 創建服務端socket */if (-1 == (ServerSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))){printf("socket error!\n");exit(1);}/* 設置服務端信息 */memset(&ServerSockAddr, 0, sizeof(ServerSockAddr)); // 給結構體ServerSockAddr清零ServerSockAddr.sin_family = AF_INET; // 使用IPv4地址ServerSockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");// 本機IP地址ServerSockAddr.sin_port = htons(1314); // 端口/* 綁定套接字 */if (-1 == bind(ServerSock, (SOCKADDR*)&ServerSockAddr, sizeof(SOCKADDR))){printf("bind error!\n");exit(1);}/* 進入監聽狀態 */if (-1 == listen(ServerSock, 10)){printf("listen error!\n");exit(1);}addr_size = sizeof(SOCKADDR);while (1){/* 監聽客戶端請求,accept函數返回一個新的套接字,發送和接收都是用這個套接字 */if (-1 == (ClientSock = accept(ServerSock, (SOCKADDR*)&ClientAddr, &addr_size))){printf("socket error!\n");exit(1);}/* 接受客戶端的返回數據 */int recv_len = recv(ClientSock, Buf, BUF_LEN, 0);printf("客戶端發送過來的數據為:%s\n", Buf);/* 發送數據到客戶端 */send(ClientSock, Buf, recv_len, 0);/* 關閉客戶端套接字 */closesocket(ClientSock);/* 清空緩沖區 */memset(Buf, 0, BUF_LEN); }/*如果有退出循環的條件,這里還需要清除對socket庫的使用*//* 關閉服務端套接字 *///closesocket(ServerSock);/* WSACleanup();*/return 0; }

客戶端程序tcp_client.c

#include <stdio.h> #include <winsock2.h>#define BUF_LEN 100int main(void) {WSADATA wd;SOCKET ClientSock;char Buf[BUF_LEN] = {0};SOCKADDR_IN ServerSockAddr;/* 初始化操作sock需要的DLL */WSAStartup(MAKEWORD(2,2),&wd); /* 向服務器發起請求 */memset(&ServerSockAddr, 0, sizeof(ServerSockAddr)); ServerSockAddr.sin_family = AF_INET;ServerSockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");ServerSockAddr.sin_port = htons(1314);while (1){/* 創建客戶端socket */if (-1 == (ClientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))){printf("socket error!\n");exit(1);}if (-1 == connect(ClientSock, (SOCKADDR*)&ServerSockAddr, sizeof(SOCKADDR))){printf("connect error!\n");exit(1);}printf("請輸入一個字符串,發送給服務端:");gets(Buf);/* 發送數據到服務端 */send(ClientSock, Buf, strlen(Buf), 0);/* 接受服務端的返回數據 */recv(ClientSock, Buf, BUF_LEN, 0);printf("服務端發送過來的數據為:%s\n", Buf);memset(Buf, 0, BUF_LEN); // 重置緩沖區closesocket(ClientSock); // 關閉套接字} // WSACleanup(); /*如果有退出循環的條件,這里還需要清除對socket庫的使用*/return 0; }

下載mingw,并加入環境變量。
上述兩個程序放在在bin目錄下
輸入
gcc tcp_server.c -o tcp_server.exe -lwsock32
gcc tcp_client.c -o tcp_client.exe -lwsock32

雙擊exe文件,一開始出現了亂碼:


在notepad中修改編碼:

使用ansi編碼

重新gcc編譯:

再次打開exe,可以正常發送數據,亂碼沒了:


(本部分windows下基于tcp的通信代碼來自公眾號:
https://mp.weixin.qq.com/s/C895Oj15jXam10xz3Z_6_w)

測試的圖片是在自己電腦上測試的。

InetAddress 類的方法

這個類表示互聯網協議(IP)地址。下面列出了 Socket 編程時比較有用的方法:

1 static InetAddress getByAddress(byte[] addr)
在給定原始 IP 地址的情況下,返回 InetAddress 對象。
2 static InetAddress getByAddress(String host, byte[] addr)
根據提供的主機名和 IP 地址創建 InetAddress。
3 static InetAddress getByName(String host)
在給定主機名的情況下確定主機的 IP 地址。
4 String getHostAddress()
返回 IP 地址字符串(以文本表現形式)。
5 String getHostName()
獲取此 IP 地址的主機名。

附錄1 TCP UDP

TCP協議
TCP(Transmission Control Protocol 傳輸控制協議)是一種面向連接的、可靠的、基于字節流的傳輸層通信協議,數據可以準確發送,數據丟失會重發。TCP協議常用于web應用中。TCP連接(三次握手)
TCP傳輸起始時,客戶端、服務端要完成三次數據交互工作才能建立連接,常稱為三次握手。
UDP協議
UDP(User Datagram Protocol, 用戶數據報協議)是一種無連接的傳輸層協議,提供面向事務的簡單不可靠信息傳送服務,可以保證通訊效率,傳輸延時小。例如視頻聊天應用中用的就是UDP協議,這樣可以保證及時丟失少量數據,視頻的顯示也不受很大影響。

附錄2 websocket

很多網站為了實現推送技術,所用的技術都是 Ajax 輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,然后由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費很多的帶寬等資源。

HTML5 定義的 WebSocket 協議,能更好的節省服務器資源和帶寬,并且能夠更實時地進行通訊。
瀏覽器通過 JavaScript 向服務器發出建立 WebSocket 連接的請求,連接建立以后,客戶端和服務器端就可以通過 TCP 連接直接交換數據。

當你獲取 Web Socket 連接后,你可以通過 send() 方法來向服務器發送數據,并通過 onmessage 事件來接收服務器返回的數據。

以下 API 用于創建 WebSocket 對象。

var Socket = new WebSocket(url, [protocol] );

WebSocket
WebSocket協議是基于TCP的一種新的網絡協議。它實現了瀏覽器與服務器全雙工(full-duplex)通信——允許服務器主動發送信息給客戶端。 WebSocket通信協議于2011年被IETF定為標準RFC 6455,并被RFC7936所補充規范。

優點
服務器可以主動傳送數據給客戶端

功能
實現了瀏覽器與服務器全雙工通信

WebSocket協議支持(在受控環境中運行不受信任的代碼的)客戶端與(選擇加入該代碼的通信的)遠程主機之間進行全雙工通信。用于此的安全模型是Web瀏覽器常用的基于原始的安全模式。 協議包括一個開放的握手以及隨后的TCP層上的消息幀。 該技術的目標是為基于瀏覽器的、需要和服務器進行雙向通信的(服務器不能依賴于打開多個HTTP連接(例如,使用XMLHttpRequest或和長輪詢))應用程序提供一種通信機制。

產生背景
簡單的說,WebSocket協議之前,雙工通信是通過多個http鏈接來實現,這導致了效率低下。WebSocket解決了這個問題。

長久以來, 創建實現客戶端和用戶端之間雙工通訊的web app都會造成HTTP輪詢的濫用: 客戶端向主機不斷發送不同的HTTP呼叫來進行詢問。

這會導致一系列的問題:

1.服務器被迫為每個客戶端使用許多不同的底層TCP連接:一個用于向客戶端發送信息,其它用于接收每個傳入消息。

2.有些協議有很高的開銷,每一個客戶端和服務器之間都有HTTP頭。

3.客戶端腳本被迫維護從傳出連接到傳入連接的映射來追蹤回復。

一個更簡單的解決方案是使用單個TCP連接雙向通信。 這就是WebSocket協議所提供的功能。 結合WebSocket API ,WebSocket協議提供了一個用來替代HTTP輪詢實現網頁到遠程主機的雙向通信的方法。

WebSocket協議被設計來取代用HTTP作為傳輸層的雙向通訊技術,這些技術只能犧牲效率和可依賴性其中一方來提高另一方,因為HTTP最初的目的不是為了雙向通訊。(獲得更多關于此的討論可查閱RFC6202)

實現原理

在實現websocket連線過程中,需要通過瀏覽器發出websocket連線請求,然后服務器發出回應,這個過程通常稱為“握手” 。在 WebSocket API,瀏覽器和服務器只需要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送。在此WebSocket 協議中,為我們實現即時服務帶來了兩大好處:

Header
互相溝通的Header是很小的-大概只有 2 Bytes

Server Push
服務器的推送,服務器不再被動的接收到瀏覽器的請求之后才返回數據,而是在有新數據時就主動推送給瀏覽器。

WebSocket 事件
以下是 WebSocket 對象的相關事件。假定我們使用了以上代碼創建了 Socket 對象:

事件 事件處理程序 描述
open Socket.onopen 連接建立時觸發
message Socket.onmessage 客戶端接收服務端數據時觸發
error Socket.onerror 通信發生錯誤時觸發
close Socket.onclose 連接關閉時觸發

方法
Socket.send()
使用連接發送數據

Socket.close()
關閉連接

為了建立一個 WebSocket 連接,客戶端瀏覽器首先要向服務器發起一個 HTTP 請求,這個請求和通常的 HTTP 請求不同,包含了一些附加頭信息,其中附加頭信息"Upgrade: WebSocket"表明這是一個申請協議升級的 HTTP 請求,服務器端解析這些附加的頭信息然后產生應答信息返回給客戶端,客戶端和服務器端的 WebSocket 連接就建立起來了,雙方就可以通過這個連接通道自由的傳遞信息,并且這個連接會持續存在直到客戶端或者服務器端的某一方主動的關閉連接。
摘錄自:
https://www.runoob.com/html/html5-websocket.html

總結

以上是生活随笔為你收集整理的【学习笔记】在windows下进行基于TCP的本地客户端和服务端socket通信的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。