歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> Unix教程

SCO UNIX下的socket編

進程通信的概念最初來源於單機系統,由於每個進程都在各自的地址范圍內運行,為了保證兩個相互通信的進程之間既不互相干擾,又協調一致的工作,操作系統為進程通信提供了相應設施,如UNIX BSD中的管道(pipe),有名管道(named pipe)和軟中斷信號(singal),UNIX system V的消息(message)、共享存儲區(shared memory)和信號量(semaphore)等,但都局限於用在本機進程之間通信。網間進程通信要解決的是不同主機進程間的通信問題(可把同機進程通信看作其中的特例)。為此,首先要解決的是網間進程標識問題。同一主機上,不同進程可以用進程號(pid)唯一標識。但在網絡環境下,各主機獨立分配的進程號不能唯一標識該進程。例如主機A賦予某進程號5,在B主機也可以存在5號進程,因此5號進程這句話就沒有意義了。其次,操作系統支持的網絡協議眾多,不同協議的工作方式不同,地址格式也不同。因此,網間進程通信還要解決多重協議的識別問題。為了解決上述問題,TCP/IP協議引入了下列幾個概念。 

端口 
  網絡中可以被命名和尋址的通信端口是操作系統可分配的一種資源。按照OSI七層協議的描述,傳輸層與網絡層最大的區別是傳輸層提供進程通信能力。從這個意義上講,網絡通信的最終地址就不僅是主機地址了,還包括可以描述進程的某種標識符。為此TCP/IP協議提出了協議端口的概念,用於標識通信的進程。 
  端口是一種抽象的軟件結構,包括一些數據結構和I/O緩沖區。應用程序即進程通過系統調用與某端口建立連接(binding)後,傳輸層傳給該端口的數據都被相應的進程所接收,相應進程發給傳輸層的數據都從該端口輸出。在TCP/IP協議的實現中,端口操作類似於一般的I/O操作,進程獲取一個端口,相當於獲取本地唯一的I/O文件,可以用一般的讀寫原語訪問。 
  類似於文件描述符,每個端口都擁有一個叫端口號的整數描述符,以區別不同端口。由於TCP/IP傳輸層的兩個協議TCP和UDP是兩個完全獨立的軟件模塊,因此各自的端口號也相互獨立。如TCP有一個255號端口,UDP也可以有一個255號端口,兩者並不沖突。 
  端口號的分配是一個重要問題,有兩種基本分配方式:第一種叫全局分配這是一種集中分配方式,由一個公認的中央機構根據用戶需要盡行統一分配,並將結果公布於眾,第二種是本地分配,又稱動態連接,即進程需要訪問傳輸層服務時,向本地操作系統提出申請,操作系統返回本地唯一的端口號,進程再通過合適的系統調用,將自己和該端口連接起來(綁定)。TCP/IP端口號的分配綜合了兩種方式。TCP/IP將端口號分為兩部分,少量的作為保留端口,以全局方式分配給服務進程。因此,每一個標准服務器都擁有一個全局公認的端口叫周知口,即使在不同的機器上,其端口號也相同。剩余的為自由端口,以本地方式進行分配。TCP和UDP規定,小於256的端口才能作為保留端口。 

地址 
  網絡通信中的兩個進程分別在兩個不同的機器上。在互連網絡中,兩台機器可以位於不同的網絡,這些網絡通過網際互連設備(網關,網橋,路由器)連接。因此需要三級尋址。 
  1。某一主機與多個網絡相連,必須指定一特定網絡地址; 
  2。網絡上美一台主機應有其唯一的地址; 
  3。美一主機上的每一進程應有在該主機上的唯一標識。 
  主機地址就是IP啦,不必多說。進程唯一標識符是十六位整數端口號。 

網絡字節順序 
  不同的計算機存放多字節值的順序不同,有的機器在起始地址存放低位字節,有的則相反。為保證數據的正確性,在網絡協議中需指定網絡字節順序。TCP/IP協議使用16位整數和32位整數的高價先存格式,他們均含在協議的頭文件中。 

連接 
  兩個進程間的通信鏈路稱為連接。連接在內部表現為一些緩沖區和一組協議機制,在外部表現出比無連接高的可靠性。 

半相關 
  綜上所述,網絡中用一個三元組可以在全局中唯一標是一個進程:(協議,本機地址,本地端口號)這樣一個三元組,叫做一個半相關,他指定連接的每半部分。 

全相關 
  一個完整的網間進程通信需要有兩個進程組成,並且只能使用同一種高層協議。也就是說TCP和UDP沒法通信。因此一個完整的網間進程通信需要一個五元組來標識: 
  (協議,本機地址,本地端口號,遠地地址,遠地端口號)這樣一個五元組叫做一個全相關。


 小馬 回復於:2003-01-15 09:40:43
有沒有樣板程序?

謝謝了


 小馬 回復於:2003-01-15 10:05:15
有沒有樣板程序?
哪位能應一下!


 lixshn 回復於:2003-01-15 12:16:31
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <signal.h>

#include <netdb.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "../incl/hbjm.h"

#define READWRITE_TIMEOUT   15
#define PKG_LEN     100

EXEC SQL   include sqlca;
EXEC SQL   include sqlda;
main()
{

    struct servent *svrent;
    struct sockaddr_in addr_in;
    int    svrsock,newsocket;
    int    childid;
    int    m_pkg=0;
    char   strTime[10];
    char   date[9];
    int    val=1;

    set_resident();        // 進程成為常駐進程

init:
    signal( SIGCHLD, sig_chld );
    memset(&addr_in,0,sizeof(struct sockaddr_in));

    addr_in.sin_family=AF_INET;
    addr_in.sin_addr.s_addr=INADDR_ANY;
    addr_in.sin_port=htons(8003);
    svrsock=socket(AF_INET,SOCK_STREAM,0);
    if ( svrsock<0 ) {
         printf("socket failed!");
         exit(-1);
    }
    if ( setsockopt(svrsock,SOL_SOCKET,SO_REUSEPORT,&val,sizeof(val)) )
    {
         printf("setsockopt failed! errno=(%d)",errno);
         exit(-1);
    }

    if( bind(svrsock,(struct sockaddr *)&addr_in,sizeof(addr_in)) ) {
        close(svrsock);
        printf("bind failed!");
        exit(-1);
    }
    if ( listen(svrsock,20) ) {
        close(svrsock);
        printf("listen failed !");
        exit(-1);
    }
    while(1)
    {

        if( ( newsocket=accept(svrsock,0,0) ) < 0 )
        {
            if( errno == EINTR )
                continue;
            else
            {
                 printf("accept failed!");
                 close(svrsock);
                 goto init;
            }
        }
        if( ( childid = fork() ) == 0 )
        {
            /* 收交易包 */
            signal(SIGALRM,r_alarm);
            alarm(READWRITE_TIMEOUT);

            if( open_database() )
            {
                close(newsocket);
                return;
            }
            if( (m_pkg= read( newsocket, r_buf, PKG_LEN )) <20 )
            {
                printf("read pkg failed!\n");
                close(newsocket);
                return;
            }

            do your work;

            if ( write( socket, snd_buf,strlen(snd_buf) ) < strlen(snd_buf) )
            {
                printf("socket write net pgklen error!\n" );
                close(newsocket);
                return;
           }
      }
      close(newsocket);

 服務端的簡單的sock通訊程序,可以看看!
Copyright © Linux教程網 All Rights Reserved