tcp的socket編程
Ⅰ 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。
Ⅱ 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 ……
Ⅲ 採用tcp協議,使用socket編程,編寫程序完成客戶端發送消息給服務端,服務端接到消息後,再發
服務端代碼:
/*server.c*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
#define PORT 4321
#define BUFFER_SIZE 1024
#define MAX_QUE_CONN_NM 5
int main()
{
struct sockaddr_in server_sockaddr, client_sockaddr;
int sin_size, recvbytes;
int sockfd, client_fd;
char buf[BUFFER_SIZE];
/*建立socket連接*/
if ((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1)
{
perror("socket");
exit(1);
}
printf("Socket id = %d\n",sockfd);
/*設置sockaddr_in 結構體中相關參數*/
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
server_sockaddr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_sockaddr.sin_zero), 8);
int i = 1;/* 使得重復使用本地地址與套接字進行綁定 */
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
/*綁定函數bind*/
if (bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr))== -1)
{
perror("bind");
exit(1);
}
printf("Bind success!\n");
/*調用listen函數*/
if (listen(sockfd, MAX_QUE_CONN_NM) == -1)
{
perror("listen");
exit(1);
}
printf("Listening....\n");
/*調用accept函數,等待客戶端的連接*/
if ((client_fd = accept(sockfd, (struct sockaddr *)&client_sockaddr, &sin_size)) == -1)
{
perror("accept");
exit(1);
}
/*調用recv函數接收客戶端的請求*/
memset(buf , 0, sizeof(buf));
if ((recvbytes = recv(client_fd, buf, BUFFER_SIZE, 0)) == -1)
{
perror("recv");
exit(1);
}
printf("Received a message: %s\n", buf);
if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1)
{
perror("send");
exit(1);
}
close(sockfd);
exit(0);
}
客戶端:
/*client.c*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#define PORT 4321
#define BUFFER_SIZE 1024
int main(int argc, char *argv[])
{
int sockfd, sendbytes;
char buf[BUFFER_SIZE];
struct hostent *host;
struct sockaddr_in serv_addr;
if(argc < 3)
{
fprintf(stderr,"USAGE: ./client Hostname(or ip address) Text\n");
exit(1);
}
/*地址解析函數*/
if ((host = gethostbyname(argv[1])) == NULL)
{
perror("gethostbyname");
exit(1);
}
memset(buf, 0, sizeof(buf));
sprintf(buf, "%s", argv[2]);
/*創建socket*/
if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
perror("socket");
exit(1);
}
/*設置sockaddr_in 結構體中相關參數*/
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(serv_addr.sin_zero), 8);
/*調用connect函數主動發起對伺服器端的連接*/
if(connect(sockfd,(struct sockaddr *)&serv_addr, sizeof(struct sockaddr))== -1)
{
perror("connect");
exit(1);
}
/*發送消息給伺服器端*/
if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1)
{
perror("send");
exit(1);
}
if ((recvbytes = recv(sockfd, buf, BUFFER_SIZE, 0)) == -1)
{
perror("recv");
exit(1);
}
close(sockfd);
exit(0);
}
Ⅳ iOS開發網路篇—Socket編程
一、網路各個協議:TCP/IP、SOCKET、HTTP等
網路七層由下往上分別為物理層、數據鏈路層、網路層、傳輸層、會話層、表示層和應用層。
其中物理層、數據鏈路層和網路層通常被稱作媒體層,是網路工程師所研究的對象;
傳輸層、會話層、表示層和應用層則被稱作主機層,是用戶所面向和關心的內容。
http協議對應於應用層
tcp協議對應於傳輸層
ip協議對應於網路層
三者本質上沒有可比性。 何況HTTP協議是基於TCP連接的。
TCP/IP是傳輸層協議,主要解決數據如何在網路中傳輸;而HTTP是應用層協議,主要解決如何包裝數據。
我 們在傳輸數據時,可以只使用傳輸層(TCP/IP),但是那樣的話,由於沒有應用層,便無法識別數據內容,如果想要使傳輸的數據有意義,則必須使用應用層 協議,應用層協議很多,有HTTP、FTP、TELNET等等,也可以自己定義應用層協議。WEB使用HTTP作傳輸層協議,以封裝HTTP文本信息,然 後使用TCP/IP做傳輸層協議將它發送到網路上。Socket是對TCP/IP協議的封裝,Socket本身並不是協議,而是一個調用介面(API),通過Socket,我們才能使用TCP/IP協議。
二、Http和Socket連接區別
相信不少初學手機聯網開發的朋友都想知道Http與Socket連接究竟有什麼區別,希望通過自己的淺顯理解能對初學者有所幫助。
2.1、TCP連接
要想明白Socket連接,先要明白TCP連接。手機能夠使用聯網功能是因為手機底層實現了TCP/IP協議,可以使手機終端通過無線網路建立TCP連接。TCP協議可以對上層網路提供介面,使上層網路數據的傳輸建立在「無差別」的網路之上。
建立起一個TCP連接需要經過「三次握手」:
第一次握手:客戶端發送syn包(syn=j)到伺服器,並進入SYN_SEND狀態,等待伺服器確認;
第二次握手:伺服器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時伺服器進入SYN_RECV狀態;
第三次握手:客戶端收到伺服器的SYN+ACK包,向伺服器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和伺服器進入ESTABLISHED狀態,完成三次握手。
握
手過程中傳送的包里不包含數據,三次握手完畢後,客戶端與伺服器才正式開始傳送數據。理想狀態下,TCP連接一旦建立,在通信雙方中的任何一方主動關閉連
接之前,TCP
連接都將被一直保持下去。斷開連接時伺服器和客戶端均可以主動發起斷開TCP連接的請求,斷開過程需要經過「四次握手」(過程就不細寫了,就是伺服器和客
戶端交互,最終確定斷開)
2.2、HTTP連接
HTTP協議即超文本傳送協議(HypertextTransfer Protocol ),是Web聯網的基礎,也是手機聯網常用的協議之一,HTTP協議是建立在TCP協議之上的一種應用。
HTTP連接最顯著的特點是客戶端發送的每次請求都需要伺服器回送響應,在請求結束後,會主動釋放連接。從建立連接到關閉連接的過程稱為「一次連接」。
1)在HTTP 1.0中,客戶端的每次請求都要求建立一次單獨的連接,在處理完本次請求後,就自動釋放連接。
2)在HTTP 1.1中則可以在一次連接中處理多個請求,並且多個請求可以重疊進行,不需要等待一個請求結束後再發送下一個請求。
由
於HTTP在每次請求結束後都會主動釋放連接,因此HTTP連接是一種「短連接」,要保持客戶端程序的在線狀態,需要不斷地向伺服器發起連接請求。通常的
做法是即時不需要獲得任何數據,客戶端也保持每隔一段固定的時間向伺服器發送一次「保持連接」的請求,伺服器在收到該請求後對客戶端進行回復,表明知道客
戶端「在線」。若伺服器長時間無法收到客戶端的請求,則認為客戶端「下線」,若客戶端長時間無法收到伺服器的回復,則認為網路已經斷開。
三、SOCKET原理
3.1、套接字(socket)概念
套接字(socket)是通信的基石,是支持TCP/IP協議的網路通信的基本操作單元。它是網路通信過程中端點的抽象表示,包含進行網路通信必須的五種信息:連接使用的協議,本地主機的IP地址,本地進程的協議埠,遠地主機的IP地址,遠地進程的協議埠。
應
用層通過傳輸層進行數據通信時,TCP會遇到同時為多個應用程序進程提供並發服務的問題。多個TCP連接或多個應用程序進程可能需要通過同一個
TCP協議埠傳輸數據。為了區別不同的應用程序進程和連接,許多計算機操作系統為應用程序與TCP/IP協議交互提供了套接字(Socket)介面。應
用層可以和傳輸層通過Socket介面,區分來自不同應用程序進程或網路連接的通信,實現數據傳輸的並發服務。
3.2 、建立socket連接
建立Socket連接至少需要一對套接字,其中一個運行於客戶端,稱為ClientSocket,另一個運行於伺服器端,稱為ServerSocket。
套接字之間的連接過程分為三個步驟:伺服器監聽,客戶端請求,連接確認。
伺服器監聽:伺服器端套接字並不定位具體的客戶端套接字,而是處於等待連接的狀態,實時監控網路狀態,等待客戶端的連接請求。
客戶端請求:指客戶端的套接字提出連接請求,要連接的目標是伺服器端的套接字。為此,客戶端的套接字必須首先描述它要連接的伺服器的套接字,指出伺服器端套接字的地址和埠號,然後就向伺服器端套接字提出連接請求。
連
接確認:當伺服器端套接字監聽到或者說接收到客戶端套接字的連接請求時,就響應客戶端套接字的請求,建立一個新的線程,把伺服器端套接字的描述發給客戶
端,一旦客戶端確認了此描述,雙方就正式建立連接。而伺服器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連接請求。
3.3、SOCKET連接與TCP連接
創建Socket連接時,可以指定使用的傳輸層協議,Socket可以支持不同的傳輸層協議(TCP或UDP),當使用TCP協議進行連接時,該Socket連接就是一個TCP連接。
3.4、Socket連接與HTTP連接
由
於通常情況下Socket連接就是TCP連接,因此Socket連接一旦建立,通信雙方即可開始相互發送數據內容,直到雙方連接斷開。但在實際網路應用
中,客戶端到伺服器之間的通信往往需要穿越多個中間節點,例如路由器、網關、防火牆等,大部分防火牆默認會關閉長時間處於非活躍狀態的連接而導致
Socket 連接斷連,因此需要通過輪詢告訴網路,該連接處於活躍狀態。
而HTTP連接使用的是「請求—響應」的方式,不僅在請求時需要先建立連接,而且需要客戶端向伺服器發出請求後,伺服器端才能回復數據。
很
多情況下,需要伺服器端主動向客戶端推送數據,保持客戶端與伺服器數據的實時與同步。此時若雙方建立的是Socket連接,伺服器就可以直接將數據傳送給
客戶端;若雙方建立的是HTTP連接,則伺服器需要等到客戶端發送一次請求後才能將數據傳回給客戶端,因此,客戶端定時向伺服器端發送連接請求,不僅可以
保持在線,同時也是在「詢問」伺服器是否有新的數據,如果有就將數據傳給客戶端。
這里我們使用Socket實現一個聊天室的功能,關於伺服器這里的就不介紹了
@interfaceViewController (){
NSInputStream *_inputStream;//對應輸入流
NSOutputStream *_outputStream;//對應輸出流
}
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *inputViewConstraint;
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *chatMsgs;//聊天消息數組
@end
懶載入這個消息數組
//從主運行循環移除
//1.建立連接
//定義C語言輸入輸出流
//把C語言的輸入輸出流轉化成OC對象
//設置代理
//把輸入輸入流添加到主運行循環
//不添加主運行循環 代理有可能不工作
//打開輸入輸出流
//登錄
//發送用戶名和密碼
//在這里做的時候,只發用戶名,密碼就不用發送
//如果要登錄,發送的數據格式為 "iam:zhangsan";
//如果要發送聊天消息,數據格式為 "msg:did you have dinner";
//登錄的指令11NSString *loginStr =@"iam:zhangsan";
//把Str轉成NSData
//建立一個緩沖區 可以放1024個位元組
//返回實際裝的位元組數
//把位元組數組轉化成字元串
//從伺服器接收到的數據
//聊天信息
//刷新表格
//發送數據
//發送完數據,清空textField
//數據多,應該往上滾動
}
//監聽鍵盤
//獲取窗口的高度
//鍵盤結束的Frm
//獲取鍵盤結束的y值