網路編程之TCP/UDP及其流程比較

來源:互聯網
上載者:User

TCP與UDP的區別

  1. 基於串連與無串連
  2. 對系統資源的要求(TCP較多,UDP少)
  3. UDP程式結構較簡單
  4. 流模式與資料報模式
    TCP保證資料正確性,UDP可能丟包
    TCP保證資料順序,UDP不保證

具體編程時的區別

  1. socket()的參數不同
  2. UDP Server不需要調用listen和accept
  3. UDP收發資料用sendto/recvfrom函數
  4. TCP:地址資訊在connect/accept時確定
    UDP:在sendto/recvfrom函數中每次均 需指定地址資訊
  5. UDP:shutdown函數無效

部分滿足以下幾點要求時,應該採用UDP 面向資料報方式

  1. 網路資料大多為短訊息
  2. 擁有大量Client
  3. 對資料安全性無特殊要求
  4. 網路負擔非常重,但對響應速度要求高

例子:ICQ、ping

伺服器程式流程(多進程):

  1. 程式初始化
  2. 填寫本機地址資訊
  3. 綁定並監聽一個固定的連接埠
  4. 收到Client的串連後建立一個socket串連
  5. 產生一個新的進程與Client進行通訊和資訊處理
  6. 子通訊結束後中斷與Client的串連

用戶端程式流程:

  1. 程式初始化
  2. 填寫伺服器位址資訊
  3. 串連伺服器
  4. 與伺服器通訊和資訊處理
  5. 通訊結束後中斷連線

伺服器代碼

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <string.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <sys/wait.h>

#define MYPORT 3490                 /* 監聽的連接埠 */

#define BACKLOG 10                 /* listen的請求接收隊列長度 */

int main() {

int sockfd, new_fd;             /* 監聽連接埠,資料連接埠 */

struct sockaddr_in sa;         /* 自身的地址資訊 */

struct sockaddr_in their_addr; /* 串連對方的地址資訊 */

int sin_size;

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

perror("socket");

exit(1);

}

sa.sin_family = AF_INET;

sa.sin_port = htons(MYPORT);         /* 網路位元組順序 */

sa.sin_addr.s_addr = INADDR_ANY;     /* 自動填本機IP */

bzero(&(sa.sin_zero), 8);             /* 其餘部分置0 */

if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {

perror("bind");

exit(1);

}

if (listen(sockfd, BACKLOG) == -1) {

perror("listen");

exit(1);

}

/* 主迴圈 */

while(1) {

sin_size = sizeof(struct sockaddr_in);

new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size));

if (new_fd == -1) {

perror("accept");

continue;

}

printf("Got connection from %s/n", inet_ntoa(their_addr.sin_addr));

if (fork() == 0) {

/* 子進程 */

if (send(new_fd, "Hello, world!/ n", 14, 0) == -1)

perror("send");

close(new_fd);

exit(0);

}

close(new_fd);

/*清除所有子進程 */

while(waitpid(-1,NULL,WNOHANG) > 0);

}

}

 

 

用戶端代碼

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <string.h>

#include <netdb.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#define PORT 3490 /* Server的連接埠 */

#define MAXDATASIZE 100 /*一次可以讀的最大位元組數 */

int main(int argc, char *argv[])

{

int sockfd, numbytes;

char buf[MAXDATASIZE];

struct hostent *he; /* 主機資訊 */

struct sockaddr_in their_addr; /* 對方地址資訊 */

if (argc != 2) {

fprintf(stderr,"usage: client hostname/n");

exit(1);

}

/* get the host info */

if ((he=gethostbyname(argv[1])) == NULL) {

/* 注意:擷取DNS資訊時,顯示出錯需要用herror而不是perror */

herror("gethostbyname");

exit(1);

}

if ((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) {

perror("socket");

exit(1);

}

their_addr.sin_family = AF_INET;

their_addr.sin_port = htons(PORT); /* short, NBO */

their_addr.sin_addr = *((struct in_addr *)he->h_addr);

bzero(&(their_addr.sin_zero), 8); /* 其餘部分設成0 */

if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {

perror("connect");

exit(1);

}

if ((numbytes=recv(sockfd,buf,MAXDATASIZE,0))==-1) {

perror("recv");

exit(1);

}

buf[numbytes] = '/0';

printf("Received: %s",buf);

close(sockfd);

return 0;

}

伺服器程式流程(單進程):

  1. 程式初始化
  2. 填寫本機地址資訊
  3. 綁定一個固定的連接埠
  4. 收到Client的資料報後進行處理與通訊
  5. 通訊結束後中斷連線

用戶端程式流程:

  1. 程式初始化
  2. 填寫伺服器位址資訊
  3. 串連伺服器
  4. 與伺服器通訊和資訊處理
  5. 通訊結束後中斷連線

UDP方式下伺服器與用戶端程式差別不大,僅第三步不同。

 

伺服器

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <string.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <sys/wait.h>

#define MYPORT 3490 /* 監聽連接埠 */

void main()

{

int sockfd; /* 資料連接埠 */

struct sockaddr_in my_addr; /* 自身的地址資訊 */

struct sockaddr_in their_addr; /* 串連對方的地址資訊 */

int sin_size, retval;

char buf[128];

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {

perror("socket");

exit(1);

}

my_addr.sin_family = AF_INET;

my_addr.sin_port = htons(MYPORT); /* 網路位元組順序 */

my_addr.sin_addr.s_addr = INADDR_ANY; /* 自動填本機IP */

bzero(&(my_addr.sin_zero), 8); /* 其餘部分置0 */

if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1) {

perror("bind");

exit(1);

}

/* 主迴圈 */

while(1) { 

retval = recvfrom(sockfd, buf, 128, 0, (struct sockaddr *)&their_addr, &sin_size);

printf("Received datagram from %s/n",inet_ntoa(their_addr.sin_addr));

if (retval == 0) {

perror (“recvfrom");

close(sockfd);

break;

}

retval = sendto(sockfd, buf, 128, 0, (struct sockaddr *)&their_addr, sin_size);

}

}

 

用戶端

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <string.h>

#include <netdb.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#define PORT 3490 /* Server的連接埠 */

#define MAXDATASIZE 100 /*一次可以讀的最大位元組數 */

int main(int argc, char *argv[])

{

int sockfd, numbytes, sin_size;

char buf[MAXDATASIZE] = “Hello, world!”;

struct hostent *he; /* 主機資訊 */

struct sockaddr_in their_addr; /* 對方地址資訊 */

if (argc != 2) {

fprintf(stderr,"usage: client hostname/n");

exit(1);

}

/* get the host info */

if ((he=gethostbyname(argv[1])) == NULL) {

herror("gethostbyname");

exit(1);

}

if ((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1) {

perror("socket");

exit(1);

}

their_addr.sin_family = AF_INET;

their_addr.sin_port = htons(PORT); /* short, NBO */

their_addr.sin_addr = *((struct in_addr *)he->h_addr);

bzero(&(their_addr.sin_zero), 8); /* 其餘部分設成0 */

numbytes = sendto(sockfd, buf, MAXDATASIZE, 0, (struct sockaddr *)&their_addr,sizeof(their_addr));

if (numbytes == -1) {

perror(“sendto");

exit(1);

}

printf(“Send: %s",buf);

numbytes = recvfrom(sockfd, buf, MAXDATASIZE, 0, (struct sockaddr *)&their_addr, &sin_size);

if (numbytes == -1) {

perror("recvfrom");

exit(1);

}

buf[numbytes] = '/0';

printf("Received: %s",buf);

close(sockfd);

return 0;

} //轉載出處:: http://www.cnblogs.com/chenxizhang/archive/2009/04/14/1435777.html

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.