程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 網絡編程——基於TCP的程序設計和基於UDP的程序設計

網絡編程——基於TCP的程序設計和基於UDP的程序設計

編輯:關於C語言

 網絡編程可分為基於TCP的網絡程序設計和基於UDP的網絡程序設計。TCP是基於字節流的面向連接的,常用於可靠的網絡傳輸,而UDP是基於數據報的無連接的網絡傳輸,常用語即時通信。

    無論是基於TCP或者是基於UDP的程序設計,它都是有固定的步驟可循的。只要理解這些步驟,實現起來也是比較簡單的。下面將介紹基於TCP和UDP的網絡編程的詳細步驟以及實現實例。

    在介紹網絡編程之前,首先要說明一點:Winsock函數是Windows提供的網絡編程的借口,無論是基於TCP的還是UDP的網絡編程,在程序設計之前,都要首先加載Winsock庫。

一、基於TCP的網絡應用程序

    網絡應用程序都是基於C/S(客戶端/服務器)模式的,因此在進行網絡應用程序開發時,不僅要開發服務器應用程序也要開發客戶端應用程序。開發服務器應用程序和客戶端應用程序在步驟上略有不同。下面介紹一下基於TCP的網絡應用程序開發的詳細步驟:

服務器端應用程序:                                                                  客戶端應用程序:

1、創建socket套接字                                                                1、創建socket套接字

2、將套接字綁定(bind)到指定的本機IP地址和端口上           

3、將套接字設為監聽模式(listen),准備接受客戶端的請求                   2、向服務器發送連接請求(connect)

4、等待客戶端請求的到來(accept),並返回新的套接字進行通信

5、服務器和客戶端相互通信(send/recv)                                         3、服務器和客戶端相互通信(send/recv) 

6、返回繼續等待新的客戶端請求到來

7、關閉socket套接字                                                                  4、關閉socket套接字

注釋:服務器要綁定端口,監聽客戶端請求,當接受到請求後才開始通信。而客戶端只需要先發送請求,只要請求被接收後就可以通信了。

在理解示例代碼之前,先介紹一些知識點和函數:

第一點:在網絡編程中,要用到IP地址和端口號,比如在bind()和accept()函數中都需要有到IP地址和端口號,在Windows API中有一個SOCKADDR_IN結構體中可以保存IP地址和端口號的信息。

第二點:服務器要綁定的IP地址應該用(INADDR_ANY)屬性,表示服務器可以接受任何端口發送來的連接請求,這是因為有的機器可能有多個網卡,因此可能有多個IP地址,這樣設定可以方便後面的程序開發。

第三點:網絡通信中用到的是網絡字節序,intel的機器本機字節序和網絡字節序的存放格式是不一樣的,所以要用想用的函數進行轉化。

inet_addr()將點分十進制的IP地址轉化為u_long型

inet_ntoa()將in_addr結構類型的參數轉化為點分十進制的IP地址

htonl()將u_long型的IP地址從主機字節序轉換為網絡字節序

htons()將u_short型的IP地址從主機字節序轉換為網絡字節序

第四點:網絡編程要用到Winsock庫,,所以不僅要加載winsock的頭文件,並且要綁定ws2_32.lib動態鏈接庫。綁定動態鏈接庫有兩種方法。第一種就是在工程的“屬性”裡設置“Link”的鏈接庫加上ws2_32.lib就可以了。第二種方法就是在工程的源文件中加上代碼:#pragma comment(lib,"ws2_32.lib")就可以了。

 /**************************************************************
                       基於TCP的服務器應用程序示例代碼
 ****************************************************************/

#include "stdafx.h"
#include <stdlib.h>
#include <Winsock2.h>
#include <stdio.h>
void main()
{
 /**************************************************************
                       加載Winsock庫
 ****************************************************************/
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
 wVersionRequested = MAKEWORD( 1, 1 );
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 )
 {
  return;
 }
 if ( LOBYTE( wsaData.wVersion ) != 1 ||
  HIBYTE( wsaData.wVersion ) != 1 )
 {
   WSACleanup( );
   return;
 }
 /**************************************************************
                  第一步:創建Winsock套接字
 ****************************************************************/
 SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);
 /**************************************************************
           第二步:將創建的套接字綁定到本地地址和端口上
 ****************************************************************/
 SOCKADDR_IN addrSrv;
 addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
 addrSrv.sin_family=AF_INET;
 addrSrv.sin_port=htons(6000);
 
 bind(sockSrv,(const sockaddr*)&addrSrv,sizeof(SOCKADDR));
 /**************************************************************
     第三步:將套接字設置為監聽模式,准備接受客戶端的請求
 ****************************************************************/
 listen(sockSrv,5);
 /**************************************************************
     第四步:接受客戶端的請求
  第五步:接收客戶端的消息和向客戶端發送消息
  第六步:返回等待
  第七步:關閉套接字
 ****************************************************************/
 SOCKADDR_IN addrClient;
 int len=sizeof(SOCKADDR);
 while(1)
 {
  SOCKET sockCon=accept(sockSrv,(SOCKADDR*)&addrClient,&len);
  char sendBuf[100];
  sprintf(sendBuf,"This is server,Welcome%s",inet_ntoa(addrClient.sin_addr));
  send(sockCon,sendBuf,strlen(sendBuf)+1,0);
  char recvbuf[100];
  recv(sockCon,recvbuf,strlen(recvbuf)+1,0);
  printf("%s\n",recvbuf);
  closesocket(sockCon);
 }
 system("PAUSE");
}

/**************************************************************
                       基於TCP的客戶端應用程序示例代碼
 ****************************************************************/

#include "stdafx.h"
#include <stdlib.h>
#include <Winsock2.h>
#include <stdio.h>
void main()
{
 /**************************************************************
                       加載Winsock庫
 ****************************************************************/
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
 wVersionRequested = MAKEWORD( 1, 1 );
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 )
 {
  return;
 }
 if ( LOBYTE( wsaData.wVersion ) != 1 ||
  HIBYTE( wsaData.wVersion ) != 1 )
 {
   WSACleanup( );
   return;
 }
 /**************************************************************
                  第一步:創建Winsock套接字
 ****************************************************************/
 SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
 /**************************************************************
                  第二步:向服務器發送連接請求
 ****************************************************************/
 SOCKADDR_IN addrSrv;
 addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
 addrSrv.sin_family=AF_INET;
 addrSrv.sin_port=htons(6000);
 connect(sockClient,(const sockaddr*)&addrSrv,sizeof(SOCKADDR));
 /**************************************************************
                  第三步:客戶端和服務器的相互通信
 ****************************************************************/
 char recvbuf[100];
 recv(sockClient,recvbuf,strlen(recvbuf)+1,0);
 printf("%s",recvbuf);
 send(sockClient,"My name is zhangsan Client",strlen("My name is zhangsan Client")+1,0);
 closesocket(sockClient);

 WSACleanup();

 system("PAUSE");

}

先運行服務器程序再運行客戶端程序,運行結果如下:

\

二、基於UDP的網絡應用程序

上面介紹了基於TCP的網絡應用程序,為了便於比較,下面介紹基於UDP的網絡應用程序的設計方法。

和上面一樣,先接受基於UDP的網絡應用程序的開發步驟:

服務器端應用程序:                                                                  客戶端應用程序:

1、創建socket套接字                                                                1、創建socket套接字

2、將套接字綁定(bind)到指定的本機IP地址和端口上                          2、向服務器發送消息(sendto)

3、如果檢測到有消息到來就接收消息(recvfrom)

4、關閉socket套接字                                                                 3、關閉socket套接字     

注釋:由於基於UDP的網絡應用程序是面向無連接的,所以不需要服務器的監聽,也不需要客戶端的連接請求。實現起來比TCP的面向連接的簡單,適用於即時通信。主要用到的函數和方法和TCP的設計方法大致一樣。示例代碼如下:

/**************************************************************
                       基於UDP的服務器應用程序示例代碼
 ****************************************************************/

#include "stdafx.h"
#include <stdlib.h>
#include <Winsock2.h>
#include <stdio.h>

#pragma comment(lib,"ws2_32.lib")
void main()
{
 /**************************************************************
                       加載Winsock庫
 ****************************************************************/
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
 wVersionRequested = MAKEWORD( 1, 1 );
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 )
 {
  return;
 }
 if ( LOBYTE( wsaData.wVersion ) != 1 ||
  HIBYTE( wsaData.wVersion ) != 1 )
 {
   WSACleanup( );
   return;
 }
 /**************************************************************
             第一步:創建Winsock套接字
 ****************************************************************/
 SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0);
 /**************************************************************
             第二步:將創建的套接字綁定到指定地址和端口上
 ****************************************************************/
 SOCKADDR_IN addrSrv;
 addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
 addrSrv.sin_family=AF_INET;
 addrSrv.sin_port=htons(6000);
 bind(sockSrv,(const sockaddr*)&addrSrv,sizeof(SOCKADDR));
 /**************************************************************
             第三步:等待並接受客戶端發送的消息
 ****************************************************************/
 SOCKADDR_IN addrClient;
 char recvBuf[100];
 int len=sizeof(SOCKADDR);
 recvfrom(sockSrv,recvBuf,100,0,(sockaddr*)&addrClient,&len);
 printf("%s",recvBuf);
 char sendBuf[100];
 sprintf(sendBuf,"This is UDP Serve! Welcome %s",inet_ntoa(addrClient.sin_addr));
 sendto(sockSrv,sendBuf,strlen(sendBuf)+1,0,
  (const sockaddr*)&addrClient,sizeof(SOCKADDR));
 closesocket(sockSrv);

 WSACleanup();
 system("pause");
}

/**************************************************************
                       基於UDP的客戶端應用程序示例代碼
 ****************************************************************/

#include "stdafx.h"
#include <stdlib.h>
#include <Winsock2.h>
#include <stdio.h>

#pragma comment(lib,"ws2_32.lib")
void main()
{
 /**************************************************************
                       加載Winsock庫
 ****************************************************************/
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
 wVersionRequested = MAKEWORD( 1, 1 );
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 )
 {
  return;
 }
 if ( LOBYTE( wsaData.wVersion ) != 1 ||
  HIBYTE( wsaData.wVersion ) != 1 )
 {
   WSACleanup( );
   return;
 }
 /**************************************************************
             第一步:創建Winsock套接字
 ****************************************************************/
 SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0);
 /**************************************************************
             第一步:向服務器發送消息
 ****************************************************************/
 SOCKADDR_IN addrClient;
 addrClient.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
 addrClient.sin_family=AF_INET;
 addrClient.sin_port=htons(6000);
 sendto(sockClient,"My name is UDP Client!",strlen("My name is UDP Client!")+1,0,
  (const sockaddr*)&addrClient,sizeof(SOCKADDR));
 char recvBuf[100];
 int len=sizeof(SOCKADDR);
 recvfrom(sockClient,recvBuf,100,0,(sockaddr*)&addrClient,&len);
 printf("%s",recvBuf);
 closesocket(sockClient);
 WSACleanup();

 system("pause");
}

運行結果如下:

\

<script type=text/javascript> if ($ != jQuery) { $ = jQuery.noConflict(); } var isLogined = false; var cb_blogId = 96439; var cb_entryId = 2208677; var cb_blogApp = "chengfeng736"; var cb_blogUserGuid = "1dbb9853-fbd5-e011-8ee0-842b2b196315"; var cb_entryCreatedDate = '2011/10/12 15:13:00'; </script> 摘自:乘風736

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved