linux 網絡編程-基礎篇


#Socket簡介

是一個編程接口
是一種特殊的文件描述符(everything in Unix is a file)
並不僅限於TCPIP協議
面向連接(Transmission Control Protocol - TCPIP)
無連接(User Datagram Protocol-UDP 和 Inter-Network Packet Exchange-IPX)

#Socket類型
流式套接字(SOCK_STREAM)
提供了一個面向連接,可靠的數據傳輸服務,數據無差錯,無重復的發送且
按發送順序接收。內設置流量控制,避免數據流淹沒慢的接收方。數據被看作是
字節流,無長度限制
數據報套接字(SOCK_DGRAM)
提供無連接服務。數據包以獨立數據包的形式被發送,不提供無差錯保證,
數據可能丟失或重復,順序發送,可能亂序接收
原始套接字(SOCK_RAW)
可以對較低層次協議如IP,ICMP直接訪問

#IP地址
IP地址是Internet中主機的標識
Internet中的主機要與別的機器通信必須具有一個IP地址
IP地址為32位(IPV4)或者128位(IPV6)
每個數據包都必須攜帶目的IP地址和源IP地址,路由器依靠此信息為數據包
選擇路由
表示形式:常用點分形式,如202.38.64.10,最后都會轉換為一個32位的無符號
整數。

#IP地址的轉換
inet_aton()
將strptr所指的字符串轉換成32位的網絡字節序二進制值
int inet_aton(const char *strptr, struct in_addr *addrptr);
inet_addr()
功能同上,返回轉換后的地址
in_addr_t inet_addr(const char *strptr);
inet_ntoa()
將32位網絡字節序二進制地址轉換成點分十進制的字符串。
char *inet_ntoa(struct in_addr inaddr);

#端口號
為了區分一台主機接收到的數據包應該轉交給哪個進程來進行處理,使用端口號
來區分
TCP端口號與UDP端口號獨立(協議不同可以使用同一個端口)
三無組:協議,IP,端口
端口號一般由IANA(Internet Assigned Numbers Authority)管理
眾所周知端口:1~1023(1~255之間為眾所周知端口,256~1023端口通常由
UNIX系統占用
已登記端口:1024~49151
動態或私有端口:49152~65535

#字節序
不同類型CPU的主機中,內存存儲多字節整數序列有兩種方法,稱為主機字節序(HBO):
小端序(little-endian)-低字節存儲在低地址
將低字節存儲在起始地址,稱為"Little-Endian"字節序,Intel,AMD等
采用的是這種方式
大端序(big-endian)-高序字節存儲在低地址
將高字節存儲在起始地址,稱為"Big-Endian"字節序,由ARM,Motorola
等所采用
網絡中傳輸的數據必須按網絡字節序,即大端字節序
在大部分PC機上,當應用進程將整數送入socket前,需要轉化成網絡字節序;當
應用進程從socket取出整數后,要轉化成小端字節序

#字節序轉換函數
把給定系統所采用的字節序稱為主機字節序,為了避免不同類別主機之間在數據
交換時由於對於字節序的不用而導致的差錯,引入了網絡字節序
主機字節序到網絡字節序:
u_long htonl(u_long hostlong);
u_short htons(u_short short);
網絡字節序到主機字節序
u_long ntohl(u_long hostlong);
u_short ntohs(u_short short);

#網絡編程相關API
int Socket(int domain, int type, int protocol);
int bind(int Sockfd, struct sockaddr *my_addr, int addrlen);
int listen(int sockfd, in backlog);
int accept(int sockfd, struct sockaddr *addr, Socklen_t *addrlen);
int connect(int sockfd, const struct sockaddr *addr, Socklen_t addrlen);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
        const struct sockaddr *dest_addr, Socklen_t addrlen);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
        struct sockaddr *src_addr, Socklen_t *addrlen);
int shutdown(int sockfd, int how);

#command:
netstat -anpt

#地址結構的一般用法
1.定義一個struct sockaddr_in類型的變量並清空
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
2.填充地址信息
myaddr.sin_family = PF_INET;
myaddr.sin_port = htons(8888);
myaddr.sin_addr.s_addr = inet_addr("192.168.1.100");
3.將該變量強制轉換為struct sockaddr類型在函數中使用
bind(listenfd,(struct sockaddr *)&myaddr, sizeof(myaddr));

#地址轉換函數
unsigned long inet_addr(const char *address);
int inet_aton(const char *cp, struct in_addr *inp);
char *inet_ntoa(struct in_addr in);

socket流程圖:

 

 

附:代碼

client.c

//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
//uint16_t htons(uint16_t hostshort);
//int atoi(const char *nptr);
//in_addr_t inet_addr(const char *cp);
//void bzero(void *s, size_t n);
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
//int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

#include <stdio.h>
#include <sys/types.h>//socket():bind();listen():accept();listen();accept();connect();
#include <sys/socket.h>//socket():bind();listen():accept();inet_addr();listen():accept();connect();
#include <arpa/inet.h>//htons();inet_addr():
#include <netinet/in.h>//inet_addr():
#include <strings.h>//bzero();
#include <stdlib.h>//atoi();exit();
#include <unistd.h>//close():
#include <string.h>

#define N 64

int main(int argc, char *argv[])
{
    if(argc < 3)
    {
        printf("Using: %s ip port\n",argv[0]);
        exit(-1);
    }
    int sockfd;
    struct sockaddr_in myaddr,peeraddr;
    char buf[N] = {0};
    size_t n;
    socklen_t mylen,peerlen;
    mylen = sizeof(myaddr);
    peerlen = sizeof(peeraddr);
    /*  creat socket  */
    if(-1 == (sockfd = socket(AF_INET,SOCK_DGRAM,0)))
    {
        perror("socket");
        exit(-1);
    }
    /* bind initialization */
    bzero(&myaddr,sizeof(myaddr));
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(atoi(argv[2])+1);
    myaddr.sin_addr.s_addr = inet_addr(argv[1]);
    /*      bind      */
    if(-1 == bind(sockfd, (struct sockaddr *)&myaddr, mylen))
    {
        perror("bind");
        exit(-1);
    }
    /*    connect    */
    bzero(&peeraddr, sizeof(peeraddr));
    peeraddr.sin_family = AF_INET;
    peeraddr.sin_port = htons(atoi(argv[2]));
    peeraddr.sin_addr.s_addr = inet_addr(argv[1]);
    //connect(sockfd,(struct sockaddr *)&peeraddr, peerlen);
    while(1){
    fgets(buf, N, stdin);
    printf("buf:%s",buf);
    if(-1 == (n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&peeraddr, peerlen)))
    {
        perror("sendto");
        exit(-1);
    }
    if(strncmp(buf, "quit", 4) == 0)
            break;
    printf("n = %d\n",n);
    }
    close(sockfd);
    exit(0);
}

server.c

#include <stdio.h>
#include <sys/types.h>//socket():bind();listen():accept();listen();accept();connect();
#include <sys/socket.h>//socket():bind();listen():accept();inet_addr();listen():accept();connect();
#include <arpa/inet.h>//htons();inet_addr():
#include <netinet/in.h>//inet_addr():
#include <strings.h>//bzero();
#include <stdlib.h>//atoi();exit();
#include <unistd.h>//close():
#include <string.h>

#define N 64

typedef struct sockaddr SA;

int main(int argc, char *argv[])
{
    if(argc < 3)
    {
        printf("Using: %s ip port\n",argv[0]);
        exit(-1);
    }

    int listenfd, connfd;
    struct sockaddr_in myaddr, peeraddr;
    char buf[N] = {0};
    size_t n;
    socklen_t mylen, peerlen;
    mylen = sizeof(myaddr);
    peerlen = sizeof(peeraddr);
    /*    create    socket    */
    if ((listenfd = (socket(PF_INET, SOCK_DGRAM, 0))) < 0)
    {
        perror("socket");
        exit(-1);
    }
    /*    bind initialization    */
    bzero(&myaddr, mylen);
    myaddr.sin_family = PF_INET;
    myaddr.sin_port = htons(atoi(argv[2]));
    inet_aton(argv[1], &myaddr.sin_addr);
    
    if(bind(listenfd,(SA *)&myaddr, sizeof(myaddr)) < 0)
    {
        perror("bind");
        exit(-1);
    }
    /*    listen        */
    listen(listenfd, 5);
    /*    accept        */
    if(-1 == (connfd = accept(listenfd, (SA *)&peeraddr, &peerlen)))
    {
        perror("accept");
        exit(-1);
    }
    printf("connect from %s: %d\n",inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));
    /*    recv-send    */
    while(1){
    n = recv(connfd, buf, N, 0);
    buf[n] = 0;
    printf("n = %d---%s\n",n,buf);
    if(0 == strncmp(buf,"quit",4))
    break; send(connfd, buf, strlen(buf), 0); } close(connfd); close(listenfd); exit(0); }


原文鏈接:http://www.cnblogs.com/lr-ting/archive/2012/08/24/2652482.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM