1、簡述基於TCP和UDP的Socket編程的異同
Socket有兩種主要的操作方式:面向連接的和無連接的。無連接的操作使用UDP數據報協議,這個操作不需要連接一個目的的socket,它只是簡單地投出數據報,快速高效,但缺少數據安全性。面向連接的操作使用TCP協議,一個這個模式的socket必須在發送數據之前與目的地的socket取得一個連接,一旦連接建立了,socket就可以使用一個流介面:打開-讀-寫-關閉,所有的發送的信息都會在另一端以同樣的順序被接收,面向連接的操作比無連接的操作效率要低,但數據的安全性更高。基於TCP的socket編程是採用的流式套接字(SOCK_STREAM)。基於UDP採用的數據報套接字(SOCK_DGRAM).
流式套接字的設計是針對面向連接的網路應用,在數據傳輸之前需要預先建立連接,在數據傳輸過程中需要維持連接,在數據傳輸結束後需要釋放連接。由於採用校驗和、確認與超時等差錯控制手段,因此流式套接字可以保證數據傳輸的正確性。
數據報套接字(SOCK_DGRAM)提供無連接的、不可靠的數據傳輸服務,實際上它是基於TCP/IP協議族中的UDP協議實現的。數據報套接字提供無序、有差錯與有重復的數據流服務。數據報套接字的設計是針對無連接的網路應用,在數據傳輸之前不需要預先建立連接。由於只採用很有限的差錯控制手段,因此數據報套接字無法保證數據傳輸的正確性。
2、udp伺服器怎麼創建多個socket描述符
DP Server程序 1、編寫UDP Server程序的步驟 (1)使用socket()來建立一個UDP socket,第二個參數為SOCK_DGRAM。 (2)初始化sockaddr_in結構的變數,專並賦值。sockaddr_in結構定義:屬 struct sockaddr_in { uint8_t sin_len; sa_family_t sin_family
3、Linux客戶端和Window伺服器端udp socket通信不能成功
上面代碼沒問題,用Linux虛擬機和window調試時,不能選用Bridge方式,改用NAT方式即可。
因為系統環境專不同,這樣屬慢慢地很容易就找到問題出在哪裡,打個比方?觸發了裡面有什麼內容,它發送一條消息少年。這類問題(是打比方,精確到埠,語言不同。列印出來看,一步一步排查就行,不限於這一個問題)
另外的可能就是linux客戶端上的代碼運行機制問題。
首先要100%確定客戶端的消息到了伺服器端,代碼上的表現可能也不同,有沒有表示什麼時候發完,這一類;
然後這時從伺服器端代碼接受消息的入口也就是第一行開始單步調試,是否觸發了伺服器的監聽函數。也就是結束符,伺服器可能一直在等單條消息的結束
4、html5的websocket怎麼建立udp連接
這個沒有辦法的,因為Websocket是基於TCP協議的。推薦使用WebRTC ,它是基於UDP協議的。
5、socket/udp 客戶端程序運行剛運行的時候可以接收伺服器發送的udp消息,但是過了一小會之後就無法收到消息
因為你發送過去 對方接收到的是你發送的埠 如果對方馬上回復的回話 你這個埠是處於監答聽狀態 信息也能收到 但過了一會兒 這個埠就被回收了 所以你要做的是 當你把消息發送過去的時候 在消息里加入你現在一直處於監聽的那個埠 讓對方知道 我這個埠一直處於監聽狀態的 這樣的話 對方把消息發到這個埠上 幾個小時之後也能收到了 用用我的吧 已經封裝好了的 http://www.cnblogs.com/SanNiuSignal/p/3812843.html
6、UDP 和 TCP 的 socket 分別一般用在什麼地方
UDP 的使用范圍很窄,而且編程比 TCP 難多了:
你真的很在乎延遲,不能忍受重傳,那麼就用UDP,例如 NTP 協議。重傳NTP消息純屬添亂。
你真的不在乎可靠性,丟一些包也不需要重傳,那麼就可以用 UDP。例子我想不出來。有人說音頻或視頻流可以用UDP,不過據我看來各大視頻網站都用HTTP協議,而HTTP是基於TCP的。
你需要NAT穿透,那麼不得不用UDP。
其他情況,一旦程序要自己做重傳,你都是在用UDP模擬出蹩腳的TCP,還不如直接用TCP呢。
總之:使用 UDP 需要有強大到不容置疑的理由,when in doubt, use TCP.
一些協議,出於歷史原因,受當時技術和網路條件限制,選擇了基於UDP實現,其選擇的理由現在很可能已經不再成立了。因此「xxx協議用UDP」不是你現在寫網路應用程序也該用UDP的理由,除非你本身就是在實現xxx協議。
另外,那些說TCP比UDP慢、效率低的,你拿UDP寫個程序,把千兆網帶寬打滿(TCP等價的代碼只有兩行:客戶端 while (true) { send(...); } 服務端 while (true) { recv(...); }。),且不說你的程序會有多復雜,先看看goodput到底是不是比TCP大、CPU使用率是不是比TCP低嘛。
7、怎麼寫一個socket編程,不管是udp的還是tcp的,可以不在同一個區域網中通信?
網路通訊很簡單的道理 通許必須有一方是公網地址 這個所謂的公網地址簡單理解就是互聯網上內公開的地容址,能夠背直接訪問的IP地址
那麼你如果想實現中國到美國的通訊(下面簡稱2方通訊)方法有一下幾種
方法1:
中國這邊或者美國那邊至少一方是具有公網IP地址的 具有公網地址的作為服務端 另外一方作為客戶端連接(具體實現就是公網一方監聽自己的公網地址上的某個埠 客戶端直接連接對方的公網地址跟埠即可)( A<=====>B(公網地址) )
方法2:
2方都具有公網地址 那就更簡單 互相連接對方的公網地址跟埠即可(A(公網)<======>B(公網))
方法3:
2方都沒有公網地址(但是其中一方或者雙方都能在路由器上做埠映射 這個問題就轉化成了方法2 或者方法1)(A(埠映射)<===========B)
方法4:
2方都沒有公網地址也無法做埠映射 這個時候就要假設一個中轉的伺服器 2方都去連接那個中轉伺服器 通過服務來轉發消息(A(內網)<===============(消息中轉伺服器)============>B(內網))
目前QQ就是用的這樣的消息傳送方式
8、UDP和Socket通信步驟
UDP Server程序
1、編寫UDP Server程序的步驟
(1)使用socket()來建立一個UDP socket,第二個參數為SOCK_DGRAM。
(2)初始化_in結構的變數,並賦值。sockaddr_in結構定義:
struct sockaddr_in {
uint8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
這里使用「08」作為服務程序的埠,使用「INADDR_ANY」作為綁定的IP地址即任何主機上的地址。
(3)使用bind()把上面的socket和定義的IP地址和埠綁定。這里檢查bind()是否執行成功,如果有錯誤就退出。這樣可以防止服務程序重復運行的問題。
(4)進入無限循環程序,使用recvfrom()進入等待狀態,直到接收到客戶程序發送的數據,就處理收到的數據,並向客戶程序發送反饋。這里是直接把收到的數據發回給客戶程序。
2、udpserv.c程序內容:
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 80
#define SERV_PORT 8888
void do_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen)
{
int n;
socklen_t len;
char mesg[MAXLINE];
for(;;)
{
len = clilen;
/* waiting for receive data */
n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);
/* sent data back to client */
sendto(sockfd, mesg, n, 0, pcliaddr, len);
}
}
int main(void)
{
int sockfd;
struct sockaddr_in servaddr, cliaddr;
sockfd = socket(AF_INET, SOCK_DGRAM, 0); /* create a socket */
/* init servaddr */
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
/* bind address and port to socket */
if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
{
perror("bind error");
exit(1);
}
do_echo(sockfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
return 0;
}
UDP Client程序
1、編寫UDP Client程序的步驟
(1)初始化sockaddr_in結構的變數,並賦值。這里使用「8888」作為連接的服務程序的埠,從命令行參數讀取IP地址,並且判斷IP地址是否符合要求。
(2)使用socket()來建立一個UDP socket,第二個參數為SOCK_DGRAM。
(3)使用connect()來建立與服務程序的連接。與TCP協議不同,UDP的connect()並沒有與服務程序三次握手。上面我們說了UDP是非連接的,實際上也可以是連接的。使用連接的UDP,kernel可以直接返回錯誤信息給用戶程序,從而避免由於沒有接收到數據而導致調用recvfrom()一直等待下去,看上去好像客戶程序沒有反應一樣。
(4)向服務程序發送數據,因為使用連接的UDP,所以使用write()來替代sendto()。這里的數據直接從標准輸入讀取用戶輸入。
(5)接收服務程序發回的數據,同樣使用read()來替代recvfrom()。
(6)處理接收到的數據,這里是直接輸出到標准輸出上。
2、udpclient.c程序內容:
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#define MAXLINE 80
#define SERV_PORT 8888
void do_cli(FILE *fp, int sockfd, struct sockaddr *pservaddr, socklen_t servlen)
{
int n;
char sendline[MAXLINE], recvline[MAXLINE + 1];
/* connect to server */
if(connect(sockfd, (struct sockaddr *)pservaddr, servlen) == -1)
{
perror("connect error");
exit(1);
}
while(fgets(sendline, MAXLINE, fp) != NULL)
{
/* read a line and send to server */
write(sockfd, sendline, strlen(sendline));
/* receive data from server */
n = read(sockfd, recvline, MAXLINE);
if(n == -1)
{
perror("read error");
exit(1);
}
recvline[n] = 0; /* terminate string */
fputs(recvline, stdout);
}
}
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in srvaddr;
/* check args */
if(argc != 2)
{
printf("usage: udpclient <IPaddress>\n");
exit(1);
}
/* init servaddr */
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
{
printf("[%s] is not a valid IPaddress\n", argv[1]);
exit(1);
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
do_cli(stdin, sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
return 0;
}
運行例子程序
1、編譯例子程序
使用如下命令來編譯例子程序:
gcc -Wall -o udpserv udpserv.c
gcc -Wall -o udpclient udpclient.c
編譯完成生成了udpserv和udpclient兩個可執行程序。
2、運行UDP Server程序
執行./udpserv &命令來啟動服務程序。我們可以使用netstat -ln命令來觀察服務程序綁定的IP地址和埠,部分輸出信息如下:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:32768 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
udp 0 0 0.0.0.0:32768 0.0.0.0:*
udp 0 0 0.0.0.0:8888 0.0.0.0:*
udp 0 0 0.0.0.0:111 0.0.0.0:*
udp 0 0 0.0.0.0:882 0.0.0.0:*
可以看到udp處有「0.0.0.0:8888」的內容,說明服務程序已經正常運行,可以接收主機上任何IP地址且埠為8888的數據。
如果這時再執行./udpserv &命令,就會看到如下信息:
bind error: Address already in use
說明已經有一個服務程序在運行了。
3、運行UDP Client程序
執行./udpclient 127.0.0.1命令來啟動客戶程序,使用127.0.0.1來連接服務程序,執行效果如下:
Hello, World!
Hello, World!
this is a test
this is a test
^d
輸入的數據都正確從服務程序返回了,按ctrl+d可以結束輸入,退出程序。
如果服務程序沒有啟動,而執行客戶程序,就會看到如下信息:
$ ./udpclient 127.0.0.1
test
read error: Connection refused
說明指定的IP地址和埠沒有服務程序綁定,客戶程序就退出了。這就是使用connect()的好處,注意,這里錯誤信息是在向服務程序發送數據後收到的,而不是在調用connect()時。如果你使用tcpmp程序來抓包,會發現收到的是ICMP的錯誤信息。
9、UDP socket最多並發多少連接
根據你的描述:
並發連接是TCP的概念,UDP只管收發數據。
要支持盡量多的終端,伺服器的處理效率要夠快,另外盡量避免多終端同時發送數據。
10、socket中tcp/ip和udp的區別
一、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函數無效
二、man----socket
通過查看socket的man手冊可以看到socket函數的第一個參數的值可以為下面這些值:
Name Purpose
PF_UNIX, PF_LOCAL Local communication
PF_INET IPv4 Internet protocols
PF_INET6 IPv6 Internet protocols
PF_IPX IPX - Novell protocols
PF_NETLINK Kernel user interface device
PF_X25 ITU-T X.25 / ISO-8208 protocol
PF_AX25 Amateur radio AX.25 protocol
PF_ATMPVC Access to raw ATM PVCs
PF_APPLETALK Appletalk
PF_PACKET Low level packet interface
三、編程區別
通常我們在說到網路編程時默認是指TCP編程,即用前面提到的socket函數創建一個socket用於TCP通訊,函數參數我們通常填為SOCK_STREAM。即socket(PF_INET, SOCK_STREAM, 0),這表示建立一個socket用於流式網路通訊。
SOCK_STREAM這種的特點是面向連接的,即每次收發數據之前必須通過connect建立連接,也是雙向的,即任何一方都可以收發數據,協議本身提供了一些保障機制保證它是可靠的、有序的,即每個包按照發送的順序到達接收方。
而SOCK_DGRAM這種是User Datagram Protocol協議的網路通訊,它是無連接的,不可靠的,因為通訊雙方發送數據後不知道對方是否已經收到數據,是否正常收到數據。任何一方建立一個socket以後就可以用sendto發送數據,也可以用recvfrom接收數據。根本不關心對方是否存在,是否發送了數據。它的特點是通訊速度比較快。大家都知道TCP是要經過三次握手的,而UDP沒有。
基於上述不同,UDP和TCP編程步驟也有些不同,如下:
TCP編程的伺服器端一般步驟是:
1、創建一個socket,用函數socket();
2、設置socket屬性,用函數setsockopt(); * 可選
3、綁定IP地址、埠等信息到socket上,用函數bind();
4、開啟監聽,用函數listen();
5、接收客戶端上來的連接,用函數accept();
6、收發數據,用函數send()和recv(),或者read()和write();
7、關閉網路連接;
8、關閉監聽;
TCP編程的客戶端一般步驟是:
1、創建一個socket,用函數socket();
2、設置socket屬性,用函數setsockopt();* 可選
3、綁定IP地址、埠等信息到socket上,用函數bind();* 可選
4、設置要連接的對方的IP地址和埠等屬性;
5、連接伺服器,用函數connect();
6、收發數據,用函數send()和recv(),或者read()和write();
7、關閉網路連接;
與之對應的UDP編程步驟要簡單許多,分別如下:
UDP編程的伺服器端一般步驟是:
1、創建一個socket,用函數socket();
2、設置socket屬性,用函數setsockopt();* 可選
3、綁定IP地址、埠等信息到socket上,用函數bind();
4、循環接收數據,用函數recvfrom();
5、關閉網路連接;
UDP編程的客戶端一般步驟是:
1、創建一個socket,用函數socket();
2、設置socket屬性,用函數setsockopt();* 可選
3、綁定IP地址、埠等信息到socket上,用函數bind();* 可選
4、設置對方的IP地址和埠等屬性;
5、發送數據,用函數sendto();
6、關閉網路連接;