socket編程tcp
① 簡述基於TCP和UDP的Socket編程的異同
Socket有兩種主要的操作方式:面向連接的和無連接的。無連接的操作使用UDP數據報協議,這個操作不需要連接一個目的的socket,它只是簡單地投出數據報,快速高效,但缺少數據安全性。面向連接的操作使用TCP協議,一個這個模式的socket必須在發送數據之前與目的地的socket取得一個連接,一旦連接建立了,socket就可以使用一個流介面:打開-讀-寫-關閉,所有的發送的信息都會在另一端以同樣的順序被接收,面向連接的操作比無連接的操作效率要低,但數據的安全性更高。基於TCP的socket編程是採用的流式套接字(SOCK_STREAM)。基於UDP採用的數據報套接字(SOCK_DGRAM).
流式套接字的設計是針對面向連接的網路應用,在數據傳輸之前需要預先建立連接,在數據傳輸過程中需要維持連接,在數據傳輸結束後需要釋放連接。由於採用校驗和、確認與超時等差錯控制手段,因此流式套接字可以保證數據傳輸的正確性。
數據報套接字(SOCK_DGRAM)提供無連接的、不可靠的數據傳輸服務,實際上它是基於TCP/IP協議族中的UDP協議實現的。數據報套接字提供無序、有差錯與有重復的數據流服務。數據報套接字的設計是針對無連接的網路應用,在數據傳輸之前不需要預先建立連接。由於只採用很有限的差錯控制手段,因此數據報套接字無法保證數據傳輸的正確性。
② socket編程·send和recv
socket的send和recv是同時支持TCP和UDP的。從這兩個函數的設計可以看出,協議簡單來說就是讀寫數據。
socket的選項是 SOCK_STREAM 。
send的返回值>0時,表示實際發送了多少位元組。 注意: 只是到系統緩存里,系統決定什麼時候會發送這些數據。
send的返回值==0時,這個在send空串時會發生,是正常的。
send的返回值<0時(只會等於-1吧),需要檢查errno,敗冊芹當 errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN 時,連接正常,可以稍後再試。其他的就是連接異常了。
recv的返回值>0時,表示實際接受到多少位元組。
recv的返回值==0時, 表示連接斷開 ,也就是收到了FIN或者RST。
recv的返回值<0時,檢查errno,和send類似。
socket的選項是 SOCK_DGRAM 。
send的返回值>0時,姿搏 返回值應該等於發送的數據長察畢度 。如果send的數據大於MTU,會在IP層分片,到達目標機器後IP層重組。
send的返回值==0時,這個只在發送空串時出現。 注意: 真的會發送空數據的。
send的返回值<0時,檢查errno,確定連接是否還正常。一般不會發生吧,UDP的send是直接發送出去的。
recv的返回值>0時, 收到一個完整的數據包 。這個完整性是有IP層保證的。
recv的返回值==0時, 收到空包,這和TCP有很大不同 。
recv的返回值<0時,檢查errno,確定socket是否正常。
PS: UDP還有兩個函數 sendto 和 recvfrom 。客戶端在調用connect後,才能用 send 和 recv , 伺服器端只能用 sendto 和 recvfrom 。
UDP無連接,無順序,自然不能代替TCP。
TCP是流式協議,需要應用層確認數據是否接受完整,也不能代替UDP。
應用要同時支持兩種協議,得在上層做包裝。有個KCP,使用UDP模擬TCP。
③ 如何編寫簡單的socket網路程序 如何編寫基於TCP協議的網路程序
下面是個人用了一個40分鍾左右的時間編寫的程序,在這編寫過程中,非常重要的一點就是: 要理解 tcp協議編寫程序的原理,即編寫伺服器端的過程,以及編寫客戶端的過程。 只要把握這兩點就可以很容易編寫出來了,但是要快速編寫出這個程序,那麼VC6.0開發工具里,最好要安裝一個番茄插件,這個插件可以快速提高你的編寫程序的效率,還有也要安裝msdn 文檔,這樣在編寫過程中,遇到對某個函數的參數想不全的時候,使用msdn就能快速幫你回憶了。 呵呵,如果你那一天去面試一家牛逼的公司的哇,很有可能就是 在筆試完成之後,就要進行機試了,這就完全考查出你的真正編程水平了。 能在極短時間里完成一個socket網路程序,那麼就可以令面試官感到非常滿意了。 不過,這個程序,還沒有連接資料庫,以後再繼續搞了。
如果你去面試 深圳科技園 那家 偉易達 集團公司的軟體工程師的哇,那麼機試題目就是這個。 當時我去面試,首先進行筆試,面試官對我筆試成績比較滿意,所以就叫我留下來吃頓飯,下午進行機試。 當時我應聘崗位是linux系統工程師C語言, 可是筆試題目,不但考核C,還考核C++,JavaScript,html。 我感覺好奇怪,心裡想,好像我是應聘VC++開發那個崗位了。 於是我等到下午,他拿來機試題目之時,才真正明白,果然是他要安排我從事VC++開發了,題目就是:編寫基於TCP/IP協議網路程序,並實現簡單的聊天程序,而且要連接資料庫。 當時我又失望了。 於是我就提出,我不想做這個題目,因為我是想應聘Linux系統C語言開發的。 就這樣失望的走了。
下面是個人完全能運行的代碼:
伺服器端源碼:
#include<stdio.h>
#include <Winsock2.h>
#pragma comment (lib,"ws2_32.lib")
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return 0;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
WSACleanup( );
return 0;
}
SOCKET socketServer=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrServer;
addrServer.sin_family=AF_INET;
addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrServer.sin_port=htons(6000);
bind(socketServer, (struct sockaddr *)&addrServer, sizeof(struct sockaddr));
listen(socketServer, 5);
SOCKADDR_IN addrClient;
int addrLen=sizeof(SOCKADDR_IN);
char sendBuf[100];
char recvBuf[100];
int i=1;
while(1)
{
printf("伺服器端等待第%d個客戶端連接請求...\n", i++);
SOCKET newsocketServer=accept(socketServer,(struct sockaddr *)&addrClient, &addrLen);
if(newsocketServer!=INVALID_SOCKET)
{
printf("伺服器端與客戶端連接成功...\n");
}
memset(sendBuf,0,100);
sprintf(sendBuf,"Welcome you to come here");
send(newsocketServer, sendBuf, strlen(sendBuf)+1,0);
memset(recvBuf,0,100);
recv(newsocketServer,recvBuf,100,0);
printf("伺服器端收到信息:%s\n",recvBuf);
closesocket(newsocketServer);
}
WSACleanup();
return 0;
}
此文章來自於個人博客: 阿浪博客 http://blog.163.com/wenxianliang08@126/
客戶端源碼:
#include<stdio.h>
#include <Winsock2.h>
#pragma comment (lib,"ws2_32.lib")
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return 0;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
WSACleanup( );
return 0;
}
SOCKET socketClient=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrServer;
addrServer.sin_family=AF_INET;
addrServer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrServer.sin_port=htons(6000);
char sendBuf[100];
char recvBuf[100];
printf("客戶端向伺服器端連接請求...\n");
int Isconnect=connect(socketClient, (struct sockaddr *)&addrServer, sizeof(struct sockaddr));
if(Isconnect!=0)
{
printf("客戶端無法連接伺服器端...\n");
return 0;
}
printf("客戶端已成功連接伺服器端...\n");
memset(recvBuf,0,100);
recv(socketClient,recvBuf,100,0);
printf("客戶端收到信息:%s\n",recvBuf);
memset(sendBuf,0,100);
sprintf(sendBuf,"Hello , I am Mr Wen !");
send(socketClient, sendBuf, strlen(sendBuf)+1,0);
closesocket(socketClient);
WSACleanup();
return 0;
}
④ Python 之 Socket編程(TCP/UDP)
socket(family,type[,protocal]) 使用給定的地址族、套接字類型、協議編號(默認為0)來創建套接字。
有效的埠號: 0~ 65535
但是小於1024的埠號基本上都預留給了操作系統
POSIX兼容系統(如Linux、Mac OS X等),在/etc/services文件中找到這些預留埠與的列表
面向連接的通信提供序列化、可靠的和不重復的數據交付,而沒有記錄邊界。意味著每條消息都可以拆分多個片段,並且每個消息片段都能到達目的地,然後將它們按順序組合在一起,最後將完整的信息傳遞給等待的應用程序。
實現方式(TCP):
傳輸控制協議(TCP), 創建TCP必須使用SOCK_STREAM作為套接字類型
因為這些套接字(AF_INET)的網路版本使用網際網路協議(IP)來搜尋網路中的IP,
所以整個系統通常結合這兩種協議(TCP/IP)來進行網路間數據通信。
數據報類型的套接字, 即在通信開始之前並不需要建議連接,當然也無法保證它的順序性、可靠性或重復性
實現方式(UDP)
用戶數據包協議(UDP), 創建UDP必須使用SOCK_DGRAM (datagram)作為套接字類型
它也使用網際網路來尋找網路中主機,所以是UDP和IP的組合名字UDP/IP
注意點:
1)TCP發送數據時,已建立好TCP連接,所以不需要指定地址。UDP是面向無連接的,每次發送要指定是發給誰。
2)服務端與客戶端不能直接發送列表,元組,字典。需要字元串化repr(data)。
TCP的優點: 可靠,穩定 TCP的可靠體現在TCP在傳遞數據之前,會有三次握手來建立連接,而且在數據傳遞時,有確認、窗口、重傳、擁塞控制機制,在數據傳完後,還會斷開連接用來節約系統資源。
TCP的缺點: 慢,效率低,佔用系統資源高,易被攻擊 TCP在傳遞數據之前,要先建連接,這會消耗時間,而且在數據傳遞時,確認機制、重傳機制、擁塞控制機制等都會消耗大量的時間,而且要在每台設備上維護所有的傳輸連接,事實上,每個連接都會佔用系統的CPU、內存等硬體資源。 而且,因為TCP有確認機制、三次握手機制,這些也導致TCP容易被人利用,實現DOS、DDOS、CC等攻擊。
什麼時候應該使用TCP : 當對網路通訊質量有要求的時候,比如:整個數據要准確無誤的傳遞給對方,這往往用於一些要求可靠的應用,比如HTTP、HTTPS、FTP等傳輸文件的協議,POP、SMTP等郵件傳輸的協議。 在日常生活中,常見使用TCP協議的應用如下: 瀏覽器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、SSH QQ文件傳輸.
UDP的優點: 快,比TCP稍安全 UDP沒有TCP的握手、確認、窗口、重傳、擁塞控制等機制,UDP是一個無狀態的傳輸協議,所以它在傳遞數據時非常快。沒有TCP的這些機制,UDP較TCP被攻擊者利用的漏洞就要少一些。但UDP也是無法避免攻擊的,比如:UDP Flood攻擊……
UDP的缺點: 不可靠,不穩定 因為UDP沒有TCP那些可靠的機制,在數據傳遞時,如果網路質量不好,就會很容易丟包。
什麼時候應該使用UDP: 當對網路通訊質量要求不高的時候,要求網路通訊速度能盡量的快,這時就可以使用UDP。 比如,日常生活中,常見使用UDP協議的應用如下: QQ語音 QQ視頻 TFTP ……
⑤ linux socket編程後是tcp還是udp
Linux socket編程既可以是TCP連接,也可以是UDP連接。Linux socket編程首先要用socket系統調用創建一個套接字,socket系統調用的原型是:
int socket(int domain, int type, int protocol);
當socket函數的type參數指定為SOCK_STREAM時,就相當於建立的是個TCP連接;當type參數指定為SOCK_DGRAM時,建立的就是一個UDP連接。當建立TCP或者UDP連接的時候,注意把第一個參數domain指定為AF_INET。
⑥ TCP 和 UDP 在socket編程中的區別
一、TCP與UDP的緩好畢區別
基於連接與無連接
對系統資源的要求(TCP較多,UDP少)
UDP程序結構較簡單
流模式與數據報模式
TCP保證數據正確性,UDP可能丟包
TCP保證數據順序,UDP不保證
部分滿足以下幾點要求時,應該採用UDP 面向數據報方式 網路數據大多為短消息
擁有大量Client
對數據安全性無特殊要求
網路負擔非常重,但對響應速度要求高
具體編程時的區別 socket()的參數不同
UDP Server不需要調用listen和accept
UDP收發數據用sendto/recvfrom函數
TCP:地址信息在connect/accept時確定
襪握UDP:擾芹在sendto/recvfrom函數中每次均 需指定地址信息
UDP:shutdown函數無效