socket-vs-udp-圖片傳送
結構體的傳送
UDP程式設計時經常需要使用sendto()和recvfrom()兩個函式,其中recvfrom()的函式原型是:
ssize_t recvfrom(
int sockfd,
void *buf,
size_t len,
int flags,
struct sockaddr *src_addr, socklen_t *addrlen
);
一般來說第二個變數buf和第三個變數len是難點。buf是指標就可以了,並不一定是char*型別,但是如果你想直接傳送和接收結構體型別的指標,往往會出錯。事實證明,還是得使用char*作為buffer來接收資料。
例子:
struct distance{
char sender;
int num_of_dests;
dv_element dve[6];
};
distance rcdv;
distance dv;
想要傳送的時候,使用
sendto(sock, (char*) &dv, sizeof (dv); , 0, (struct sockaddr *) &echoServAddr, sizeof (echoServAddr));
想要接收的時候,使用
recvfrom(sock, (char*) &rcdv, sizeof(struct distance) , 0,(struct sockaddr *) &fromAddr, &fromSize))
- 這兩個函式都把想要傳送(接收)的結構體的地址強制轉換成了char*型,沒有出錯,資料都很完整。若是不完整,可以考慮傳送之前自己寫一段程式碼把要傳送的結構體裡的內容存入char*型裡,然後傳送這個char*型變數,接收時,寫一段程式碼把這個char*型變數讀到結構體裡.
借鑑:https://blog.csdn.net/golzygo/article/details/8214748
Socket緩衝區
-
每一個socket在被建立之後,系統都會給它分配兩個緩衝區,即輸入緩衝區和輸出緩衝區。
-
sendto函式並不是直接將資料傳輸到網路中,而是負責將資料寫入輸出緩衝區,資料從輸出緩衝區傳送到目標主機是由協議完成的。資料寫入到輸出緩衝區之後,sendto函式就可以返回了,資料是否傳送出去,是否傳送成功,何時到達目標主機,都不由它負責了,而是由協議負責。
-
recv函式也是一樣的,它並不是直接從網路中獲取資料,而是從輸入緩衝區中讀取資料。
-
輸入輸出緩衝區,系統會為每個socket都單獨分配,並且是在socket建立的時候自動生成的。一般來說,預設的輸入輸出緩衝區大小為8K。套接字關閉的時候,輸出緩衝區的資料不會丟失,會由協議傳送到另一方;而輸入緩衝區的資料則會丟失。
sendto函式工作原理:
-
send函式只負責將資料提交給協議層。
-
當呼叫該函式時:
1.send先比較待發送資料的長度len和套接字s的傳送緩衝區的長度 如果len大於s的傳送緩衝區的長度,該函式返回SOCKET_ERROR; 2.如果len小於或者等於s的傳送緩衝區的長度,那麼send先檢查協議是否正在傳送s的傳送緩衝中的資料; 如果是就等待協議把資料傳送完, 3.如果協議還沒有開始傳送s的傳送緩衝中的資料或者s的傳送緩衝中沒有資料,那麼send就比較s的傳送緩衝區的剩餘空間和len; 如果len大於剩餘空間大小,send就一直等待協議把s的傳送緩衝中的資料傳送完, 4.如果len小於剩餘空間大小,send就僅僅把buf中的資料copy到剩餘空間裡(注意並不是send把s的傳送緩衝中的資料傳到連線的另一端的,而是協議傳的,send僅僅是把buf中的資料copy到s的傳送緩衝區的剩餘空間裡)。 如果send函式copy資料成功,就返回實際copy的位元組數, 如果send在copy資料時出現錯誤,那麼send就返回SOCKET_ERROR; 如果send在等待協議傳送資料時網路斷開的話,那麼send函式也返回SOCKET_ERROR。 要注意send函式把buf中的資料成功copy到s的傳送緩衝的剩餘空間裡後它就返回了, 但是此時這些資料並不一定馬上被傳到連線的另一端。 如果協議在後續的傳送過程中出現網路錯誤的話,那麼下一個Socket函式就會返回SOCKET_ERROR。 (每一個除send外的Socket函式在執行的最開始總要先等待套接字的傳送緩衝中的資料被協議傳送完畢才 能繼續,如果在等待時出現網路錯誤,那麼該Socket函式就返回SOCKET_ERROR)
recv函式工作原理:
- 當呼叫該函式時:
recv先檢查套接字s的接收緩衝區 如果s接收緩衝區中沒有資料或者協議正在接收資料,那麼recv就一直等待,直到協議把資料接收完畢。 當協議把資料接收完畢,recv函式就把s的接收緩衝中的資料copy到buf中. (注意協議接收到的資料可能大於buf的長度,所以在這種情況下要呼叫幾次recv函式才能把s的接收緩衝中的資料copy完。 recv函式僅僅是copy資料,真正的接收資料是協議來完成的) recv函式返回其實際copy的位元組數。 如果recv在copy時出錯,那麼它返回SOCKET_ERROR; 如果recv函式在等待協議接收資料時網路中斷了,那麼它返回0 。 對方優雅的關閉socket並不影響本地recv的正常接收資料; 如果協議緩衝區內沒有資料,recv返回0,指示對方關閉; 如果協議緩衝區有資料,則返回對應資料(可能需要多次recv),在最後一次recv時,返回0,指示對方關閉。 學習:https://blog.csdn.net/rankun1/article/details/50488989 推薦: https://blog.csdn.net/u010270148/article/details/53605339?utm_source=blogxgwz12
UDP丟包
UDP主要丟包原因及具體問題分析
- 主要丟包原因
-
接收端處理時間過長導致丟包:呼叫recv方法接收端收到資料後,處理資料花了一些時間,處理完後再次呼叫recv方法,在這二次呼叫間隔裡,發過來的包可能丟失。對於這種情況可以修改接收端,將包接收後存入一個緩衝區,然後迅速返回繼續recv。
-
傳送的包巨大丟包:雖然send方法會幫你做大包切割成小包傳送的事情,但包太大也不行。例如超過50K的一個udp包,不切割直接通過send方法傳送也會導致這個包丟失。這種情況需要切割成小包再逐個send。
-
傳送的包較大,超過接受者快取導致丟包:包超過mtu size數倍,幾個大的udp包可能會超過接收者的緩衝,導致丟包。這種情況可以設定socket接收緩衝。以前遇到過這種問題,我把接收緩衝設定成64K就解決了。
int nRecvBuf=32*1024;//設定為32K setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
-
傳送的包頻率太快:雖然每個包的大小都小於mtu size 但是頻率太快,例如40多個mut size的包連續傳送中間不sleep,也有可能導致丟包。這種情況也有時可以通過設定socket接收緩衝解決,但有時解決不了。所以在傳送頻率過快的時候還是考慮sleep一下吧。
-
區域網內不丟包,公網上丟包。這個問題我也是通過切割小包並sleep傳送解決的。如果流量太大,這個辦法也不靈了。總之udp丟包總是會有的,如果出現了用我的方法解決不了,還有這個幾個方法: 要麼減小流量,要麼換tcp協議傳輸,要麼做丟包重傳的工作。
UDP資料傳輸中出現的分包問題的解釋
如果我們定義的TCP和UDP包小於1452,1464,那麼我們的包在IP層就不用分包了,這樣傳輸過程中就避免了在IP層組包發生的錯誤。如果使用UDP協議,如果IP層組包發生錯誤,那麼包就會被丟棄,UDP不保證可靠傳輸。但是TCP發生組包錯誤時,該包會被重傳,保證可靠傳輸。所以,我們在用Socket程式設計時,包的大小設定不一定非要小於1400,UDP協議要求包小於64K,TCP沒有限定 。
-
udp本身就是不可靠,亂序的。
首先 sendto 傳送端,當socket傳送緩衝佔滿,會有階段性丟包出現。
其次 recvfrom 接收端 當socket接收緩衝滿,由於TCP/IP協議棧是執行在核心態,recvfrom並不會在使用者態被立即呼叫,而且由於TCP/IP協議棧的內部鎖的存在,這個時候是線性執行,而不是併發執行,那麼後續包會被丟棄,也就是出現你說的 抓包可以抓到,但是你的程式接收不到的現象,因為使用者態無法及時響應,導致核心態的緩衝長時間處於高負載狀態,結局就是,隨著時間的推移丟包越來越多。
簡單的臨時化解,可以採用的方法:
[1] 增加接收端socket的接收緩衝大小例如到 510241024, 呼叫setsocketopl函式
[2] 檢測傳送端sendto 的返回值,當出現SOCKET=ERROR,使用select 等SOCKET緩衝被清除 -
UDP與TCP一樣,屬於傳輸層協議,而鏈路層有個MTU(最大傳輸單元)
因特網協議允許IP分片,這樣就可以將資料包分成足夠小的片段以通過那些最大傳輸單元小於該資料包原始大小的鏈路了。 這一分片過程發生在網路層,傳輸層是 OSI 模型中最重要的一層,這裡是根據視窗控制傳輸,而非MTU。 傳輸協議同時進行流量控制或是基於接收方可接收資料的快慢程度規定適當的傳送速率。 除此之外,傳輸層按照網路能處理的最大尺寸將較長的資料包進行強制分割。 例如,乙太網無法接收大於1500位元組的資料包。 傳送方節點的傳輸層將資料分割成較小的資料片, 同時對每一資料片安排一序列號,以便資料到達接收方節點的傳輸層時,能以正確的順序重組, 該過程即被稱為排序。 它使用的是將分組傳送到鏈路上的網路介面的最大傳輸單元的值。 原始分組的分片都被加上了標記,這樣目的主機的TCP層就能將分組重組成原始的資料包了。
-
乙太網的資料幀長度不能大於1500位元組(乙太網物理特性決定),這個1500位元組也就是網路層(IP層)資料報文的最大長度。鏈路層 首部和尾部共有18個位元組,資料區即為MTU往上看網路層,網路層有IP資料報文的頭,佔了20個位元組,所以實際資料長度為1480個位元組。這個1480長度的資料就是TCP或UDP傳來的傳來的資料。再往上看,由於在傳輸層UDP協議頭佔了8個位元組,故實際的資料長度為1472個位元組(此資料即為我們可存放封裝的最大資料長度)故在區域網環境下,採用UDP協議傳輸資料,最大封裝的資料長度為1472個位元組。而Internet上標準的MTU值為576,故資料封裝的最大長度576-20-8=548個位元組,資料長度小於此值,則不容易出現分包情況。
圖片傳送
圖片時二進位制檔案,通過檔案流進行讀取和傳送
// server2.cpp : 此檔案包含 "main" 函式。程式執行將在此處開始並結束。
//
#include"pch.h"
#include <iostream>
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
//建立套接字
SOCKET createSocket();
//判斷檔案是否存在
BOOL IsDirExist(char cdir[]);
//獲取檔案儲存的根路徑
char* piturePath(char name[]);
//開啟圖片
void openPicture(FILE* &p, char path[], SOCKET sSocket);
struct Picture
{
long length;
char buffer[4096];
int flag;
//string success;
}picture;
int main() {
//建立伺服器套接字
SOCKET sSocket = createSocket();
//建立結構地址變數
sockaddr_in serveraddr;
sockaddr_in clientaddr;
int slen = sizeof(serveraddr);
int clen = sizeof(clientaddr);
//設定伺服器的地址
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(8999);
serveraddr.sin_addr.S_un.S_addr = INADDR_ANY;
//把地址繫結到伺服器
int ret = bind(sSocket, (SOCKADDR*)&serveraddr, slen);
if (ret == SOCKET_ERROR)
{
cout << "bind failed " << endl;
closesocket(sSocket);
WSACleanup();
cout << "2s後退出控制檯!" << endl;
Sleep(2000);
exit(0);
}
char data[200]; //接收短資料的緩衝區
memset(data, 0, sizeof(data)); //初始化緩衝區
//char dir[50] = { 0 }; //存放目錄的緩衝區
char begin[] = "好的,準備接受圖片。"; //開始標誌訊息
char end[] = "接收圖片完成。"; //結束標誌訊息
int iRcv; //接受狀態
int iSend; //傳送狀態
FILE *p; //檔案指標
/* 傳送的包較大,超過接受者快取導致丟包:
包超過mtu size數倍,幾個大的udp包可能會超過接收者的緩衝,導致丟包。
這種情況可以設定socket接收緩衝。 */
//int nRecvBuf = 128 * 1024;//設定為128K
//setsockopt(sSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&nRecvBuf, sizeof(int));
//迴圈接收圖片
while (1) {
cout << "=================================================Server===============================================" << endl;
//接收客戶端的開始訊息
iRcv = recvfrom(sSocket, data, sizeof(data), 0, (SOCKADDR*)&clientaddr, &clen);
if (iRcv == SOCKET_ERROR) {
cout << "接受資訊失敗!" << endl;
cout << "2s後退出控制檯!" << endl;
closesocket(sSocket);
WSACleanup();
Sleep(2000);
exit(0);
}
cout << "Client: " << data << endl;
memset(data, 0, sizeof(data));
//傳送回饋訊息給客戶端
iSend = sendto(sSocket, begin, strlen(begin), 0, (SOCKADDR*)&clientaddr, clen);
if (iSend == SOCKET_ERROR) {
cout << "傳送資訊失敗!" << endl;
cout << "2s後退出控制檯!" << endl;
closesocket(sSocket);
WSACleanup();
Sleep(2000);
exit(0);
}
cout << "Server: " << begin << endl;
//接收圖片名字
iRcv = recvfrom(sSocket, data, sizeof(data), 0, (SOCKADDR*)&clientaddr, &clen);
if (iRcv == SOCKET_ERROR) {
cout << "接受資訊失敗!" << endl;
cout << "2s後退出控制檯!" << endl;
closesocket(sSocket);
WSACleanup();
Sleep(2000);
exit(0);
}
//獲取圖片存放的根路徑
cout << "接收的圖片名字: " << data << endl;
char *path = piturePath(data);
cout << "path= " << path << endl;
memset(data, 0, sizeof(data));
//開啟圖片
openPicture(p, path, sSocket);
cout << "····接收中····" << endl;
//int count = 1;
picture.flag = 0;
while (!picture.flag) {
//cout << count << endl;
//count++;
//cout << "1";
memset(picture.buffer, 0, sizeof(picture.buffer));
//cout << "2";
iRcv = recvfrom(sSocket, (char*)&picture, sizeof(struct Picture), 0, (SOCKADDR*)&clientaddr, &clen);
//cout << "iRcv==" << iRcv << endl;
if (iRcv == SOCKET_ERROR) {
cout << "接受圖片失敗!" << endl;
cout << "2s後退出控制檯!" << endl;
closesocket(sSocket);
WSACleanup();
Sleep(2000);
return -8;
}
if (iRcv == 0) //客戶端已經關閉連線
{
printf("Client has closed the connection\n");
return 0;
}
fwrite(picture.buffer, picture.length, 1, p);
//cout << "4" << endl;
//接受一次包就確認一次
char success[] = "success";
iSend = sendto(sSocket, success, strlen(success), 0, (SOCKADDR*)&clientaddr, clen);
if (iSend == SOCKET_ERROR) {
cout << "傳送資訊失敗!" << endl;
cout << "2s後退出控制檯!" << endl;
closesocket(sSocket);
WSACleanup();
Sleep(2000);
return -10;
}
//cout << "Server: " <<success << endl;
memset(success, 0, sizeof(success));
//fseek(p, 0, 2);
//cout << "內容" << picture.buffer << endl;
}
cout << "····接收中····" << endl;
cout << "····接收完成····" << endl;
cout << endl;
iRcv = recvfrom(sSocket, data, sizeof(data), 0, (SOCKADDR*)&clientaddr, &clen);
if (iRcv == SOCKET_ERROR) {
cout << "接受資訊失敗!" << endl;
cout << "2s後退出控制檯!" << endl;
closesocket(sSocket);
WSACleanup();
Sleep(2000);
return -9;
}
cout << "Client: " << data << endl;
memset(data, 0, sizeof(data));
iSend = sendto(sSocket, end, strlen(end), 0, (SOCKADDR*)&clientaddr, clen);
if (iSend == SOCKET_ERROR) {
cout << "傳送資訊失敗!" << endl;
cout << "2s後退出控制檯!" << endl;
closesocket(sSocket);
WSACleanup();
Sleep(2000);
return -10;
}
cout << "Server: " << end << endl;
iRcv = recvfrom(sSocket, data, sizeof(data), 0, (SOCKADDR*)&clientaddr, &clen);
if (iRcv == SOCKET_ERROR) {
cout << "接受資訊失敗!" << endl;
cout << "2s後退出控制檯!" << endl;
closesocket(sSocket);
WSACleanup();
Sleep(2000);
return -11;
}
cout << "Client: " << data << endl;
//cout << strcmp(data, "byebye") << endl;
if (!(strcmp(data, "byebye"))) {
cout << "2m後關閉伺服器連線!";
Sleep(200000);
break;
}
memset(data, 0, sizeof(data));
fclose(p);
p = NULL;
cout << endl;
cout << endl;
}
//關閉,清理
closesocket(sSocket);
WSACleanup();
return 0;
}
//建立socket
SOCKET createSocket() {
WORD version = MAKEWORD(2, 2);
WSADATA wsadata;
if (WSAStartup(version, &wsadata))
{
cout << "WSAStartup failed " << endl;
cout << "2s後控制檯將會關閉!" << endl;
Sleep(2000);
exit(0);
}
//判斷版本
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wVersion) != 2)
{
cout << "wVersion not 2.2" << endl;
cout << "2s後控制檯將會關閉!" << endl;
Sleep(2000);
exit(0);
}
SOCKET sSocket;
sSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (SOCKET_ERROR == sSocket)
{
cout << "socket failed" << endl;
cout << "2s後控制檯將會關閉!" << endl;
Sleep(2000);
exit(0);
}
else {
return sSocket;
}
}
// 判斷資料夾是否存在
BOOL IsDirExist(char cdir[])
{
string dir(cdir);
size_t origsize = dir.length() + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t *wcstring = (wchar_t *)malloc(sizeof(wchar_t)*(dir.length() - 1));
mbstowcs_s(&convertedChars, wcstring, origsize, dir.c_str(), _TRUNCATE);
DWORD dwAttrib = GetFileAttributes(wcstring);
return INVALID_FILE_ATTRIBUTES != dwAttrib && 0 != (dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
}
//圖片儲存的根路徑
char* piturePath(char name[]) {
char dir[50] = { 0 };
while (true)
{
cout << "請輸入圖片存放路徑: " << endl;
cin >> dir;
if (IsDirExist(dir)) {
break
相關推薦
socket-vs-udp-圖片傳送
結構體的傳送
UDP程式設計時經常需要使用sendto()和recvfrom()兩個函式,其中recvfrom()的函式原型是:
ssize_t recvfrom(
int sockfd,
void *buf,
size_t len,
int flags,
Windows socket程式設計 udp協議傳送封裝自定義幀
最近在出差,要在內網做個傳送自定義幀結構的資料的程式,一時間沒做過這類東西,在網上學習了許多新的概念,也回顧了網路程式設計課上所學的關於網路位元組序的相關知識,總結如下:
自定義幀結構如下:
需要用到的東西包括子系統編號,裝置編號,資訊型別,資料體長度,資料體
作為傳送
通過socket實現接收和傳送圖片檔案
今天採用udp協議實現接收和傳送圖片檔案,圖片格式是bmp。
udp提供面向事務的簡單不可靠資訊傳送服務,具有較好的實時性,它是一種無連線的傳輸層協議,工作效率比TCP高。
udp客戶端程式設計一般步驟:
1 、建立socket套接字
2 、配置ip port 協議簇
3 、se
26 API-網路程式設計(網路概述,Socket通訊機制,UDP協議傳送和接收資料,TCP協議傳送和接收資料)
1:網路程式設計(理解)
(1)網路程式設計:用Java語言實現計算機間資料的資訊傳遞和資源共享(2)網路程式設計模型
l網路模型一般是指
OSI(Open System Interconnection開放系統互連)參考模型
TCP/IP參考模型
(3)網路程式
Android socket通過UDP的方式傳送,接收資料
Android socket通過UDP的方式來發送和接收資料,從而進行手機間的通訊。
傳送方:
public class SendToAIUIUtils {
private static InetAddress mAddress;
p
使用DatagramSocket傳送、接收資料(Socket之UDP套接字)
17.4.2 使用DatagramSocket傳送、接收資料(1)
Java使用DatagramSocket代表UDP協議的Socket,DatagramSocket本身只是碼頭,不維護狀態,不能產生IO流,它的唯一作用就是接收和傳送資料報,Java使用DatagramP
SOCKET, TCP/UDP, HTTP, FTP 淺析
net telnet 應用層 base 中間節點 簡單網絡管理協議 sock 協議 主動
SOCKET, TCP/UDP, HTTP, FTP
(一)TCP/UDP,SOCKET,HTTP,FTP簡析
TCP/IP是個協議組,可分為三個層次:網絡層、傳
【Windows socket+IP+UDP+TCP】網絡基礎
south 分享 .net 子郵件 sock 數據 data get 電子
Windows Socket+網絡 Winsock是 Windows下套接字標準。 Winsock 編程分為UDP【Windows socket + UDP】,TCP【W
TCP vs UDP
requires pro syn height pack IT rec tac CP
Connection
TCP is a connection-oriented protocol.
UDP is a connectionless protocol.
Funct
Linux——Socket之UDP程式設計
一、linux網路通訊的BSD套接字(Berkeley Software Distribution) 包括三種方式:1、流式(可靠TCP)2、資料表(面向報文UDP)3、原始(訪問底層協議) 端式:大端(最高位元組先發現)小端(最低位元組先發現) 通訊端點(繫結IP地址,埠號)
socket程式設計UDP協議以及注意事項
//伺服器
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <
【Android開發—智慧家居系列】(四):UDP通訊傳送指令
【Android開發—智慧家居系列】(四):UDP通訊傳送指令
思路回顧
【1】手機連線WIFI模組 【2】UDP通訊對WIFI模組傳送指令,以和WIFI模組保持連線狀態 【3】UDP通訊對WIFI模組傳送指令,讓其搜尋可用的無線網,返回WIFI列表
C#Socket通訊基礎(非同步Socket通訊UDP)
一、通訊原理參考https://blog.csdn.net/xiaochenXIHUA/article/details/83446031。
非同步通訊解決同步通訊的缺點可以雙向傳送和接收資訊;非同步通訊思路是引入多執行緒機制,在一個程序中使用兩個執行緒,分別處理接收執行緒與傳送執行緒,這種機制稱
C#Socket通訊基礎(同步Socket通訊UDP)
一、UDP通訊原理
UDP協議使用無連線的套接字,因此不需要再網路裝置之間傳送連線資訊,但是必須用Bind方法繫結到一個本地地址/埠上。
①建立套接字
②繫結IP地址和埠作為伺服器端
③直接使用SendTo/ReceiveFrom來執行操作
注意:同步Socket(UDP)通訊存
多執行緒實現UDP協議傳送、接收資料
放碼過來吧!
public class ChatRoom {
public static void main(String[] args) throws SocketException {
DatagramSocket sendSocket =
SylixOS 網路協議棧lwip介紹2-----UDP資料傳送流程
UDP資料包的傳送是通過sendto()發起的(其他介面類似),整體實現流
程如下:
(1) 通過檔案描述符fd獲取檔案結構,並提取lwipfd。再通過lwipfd從socket表中獲取socket結構。Socket結構中包含了此udp連結中的connec
Spring Boot整合websocket實現群聊,點對點聊天,圖片傳送,音訊傳送
參考:基於https://blog.csdn.net/qq_38455201/article/details/80374712 基礎上進行新增圖片傳送和音訊傳送功能
單點圖片傳送:
單點音訊傳送:
音訊傳送相關js參考:https://github.
1、【網路程式設計】Socket/TCP/UDP/HTTP/HTTPS/網路分層模型
一、簡介
1、相關概念
TCP:傳送控制協議(Transmission Control Protocol)
UDP:使用者資料報協議 (UDP:User Datagram Protocol)
HTTP:全稱是HyperText Transfer Pro
Linux中用socket實現UDP網路程式
這篇部落格的目的是想實現一個簡單的UDP伺服器程式,完成客戶端與伺服器端的通訊。
因為涉及的小知識點比較多,所以本篇部落格的篇幅較長,但是會講的很詳細。
在下一篇部落格裡,我會總結Linux中用socket實現TCP網路程式
1.程式的第一步是建立套接字(so
javaSE (三十九)網路程式設計(網路程式設計三要素和Socket、UDP傳輸、多執行緒UDP傳輸)
1、網路程式設計三要素:
地址:定位電腦 本地迴路地址:127.0.0.1 廣播地址:255.255.255.255
埠號:定位電腦中的程式 o~65525 儘量使用1024以上的
協議:資料交換的規則/標準 UDP: 面向無連線,資料不安全,速度快,不區分客戶端與服