1. 程式人生 > >TCP與UDP協議socket函式例項理解

TCP與UDP協議socket函式例項理解

socket 函式

int socket(int domain, int type, int protocol)

返回值: 非負描述符為成功,-1則出錯
domain: 指明的是網路層協議族/域,通常AF_INET、AF_INET6、AF_LOCAL等
type: 套介面型別,主要SOCK_STREAM、SOCK_DGRAM、SOCK_RAW
protocol:一般取為0。成功時,返回一個小的非負整數值,與檔案描述符類似。

地址資訊結構體

struct sockaddr 
{
    sa_family_t  sa_family;//協議族
    char         sa_data[14];//包含了IP與埠號
}

為了方便使用一般使用struct sockaddr_in 賦值:

struct sockaddr_in
{
    __SOCKADDR_COMMON (sin_);
in_port_t sin_port;                     /* Port number. */
struct in_addr sin_addr;            /* Internet address. */
/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) -
                       __SOCKADDR_COMMON_SIZE -
                       sizeof (in_port_t) -
                       sizeof (struct in_addr)];     
                       /* 字元陣列sin_zero[8]的存在是為了保證結構體struct sockaddr_in的大小和結構體struct sockaddr的大小相等 */};

TCP:

client:

int main()
{
    int sockefd = socket(AF_INET,SOCK_STREAM,0);//建立socket,AF_INET表示IPv4協議族,SOCK_STREAM表示TCP協議
    if (socket < 0)
    {
        perror("get socket fail");
        return -1;
    }
    struct sockaddr_in saddr;
    memset(&saddr , 0 ,sizeof(struct sockaddr));//結構體置零
    saddr.sin_family=AF_INET;//使用IP協議族
saddr.sin_port=htons(8000);//埠號轉換為高位儲存 saddr.sin_addr.s_addr =inet_addr("192.168.1.85");//將點分字元伺服器IP地址轉為二進位制儲存 if(connect(sockefd ,(struct sockaddr*)&saddr,sizeof(struct sockaddr))<0)//連結伺服器 { perror("connect fail"); return -1; } char buf[12] = "123" ; if(send(sockefd,buf,strlen(buf)+1,0)<0)//向伺服器傳送字串buf 大小為sizeof(buf)+1, { perror("send fail"); return 0; } close(sockefd);//關閉socket。 }

server:

int main(void)
{
    int sockefd = socket(AF_INET,SOCK_STREAM,0);//建立自己的socket
    if (sockefd < 0)
    {
        perror("get sockefd fail");
        return -1;
    }
    struct sockaddr_in saddr,caddr;
    memset( &saddr, 0 , sizeof(struct sockaddr) );
    saddr.sin_family=AF_INET;
    saddr.sin_port=htons(4000);
    saddr.sin_addr.s_addr =inet_addr("192.168.1.81");
    if(bind(sockefd,(struct sockaddr *)&saddr,sizeof(saddr))<0)//把socket 跟ip和PORT 繫結.
    {
        perror("bind fail ");
        return -1;
    }
    listen(sockefd,5);//監聽,佇列為5
    memset(&caddr , 0 ,sizeof(struct sockaddr));
    int sizes=sizeof(caddr);
    int newsockefd = accept(sockefd,(struct sockaddr *)&caddr,&sizes);//捕獲客戶端socket資訊存放到caddr中
    char *ip = malloc(sizeof(char)*16);
    ip = inet_ntoa(caddr.sin_addr);
    //send(newsockefd,buf,strlen(buf),0)
    char rbuf[12];
    recv(newsockefd,rbuf,sizeof(rbuf),0);//接收資訊
    printf(" port : %-12d \n ip   : %-12s \n get  : %-12s \n",caddr.sin_port,ip,rbuf );
    close(sockefd);
    close(newsockefd);
}

UDP:

client:

int main(int argc, char const *argv[])
{
    int sockefd = socket(AF_INET,SOCK_DGRAM,0);//建立socket,SOCK_DGRAM為UDP協議
    if (socket<0)
    {
        perror("socket fail");
        return -1;
    }
    struct sockaddr_in saddr,caddr;
    memset( &saddr, 0 , sizeof(struct sockaddr) );
    saddr.sin_family=AF_INET;
    saddr.sin_port=htons(4000);
    saddr.sin_addr.s_addr =inet_addr("192.168.1.81");
    char buf[] = "hello world";
    size_t len = strlen(buf)+1;
    socklen_t size = sizeof(struct sockaddr_in);
    sendto(sockefd, buf, len, 0,(struct sockaddr*)&saddr, size);//傳送資訊
    return 0;
}

server:

int main (void)
{
    int sockefd = socket(AF_INET,SOCK_DGRAM,0);
    if (socket<0)
    {
        perror("socket fail");
        return -1;
    }
    struct sockaddr_in saddr,caddr;
    memset( &saddr, 0 , sizeof(struct sockaddr) );
    saddr.sin_family=AF_INET;
    saddr.sin_port=htons(4000);
    saddr.sin_addr.s_addr =inet_addr("192.168.1.81");
    if(bind(sockefd,(struct sockaddr *)&saddr,sizeof(saddr))<0)//繫結IP埠與socket,UDP中,誰先接收,需先繫結
    {
        perror("bind fail ");
        return -1;
    }
    char buf[100];
    socklen_t size = sizeof(struct sockaddr_in);
    recvfrom(sockefd, buf, sizeof(buf), 0, (struct sockaddr*)&caddr, &size);//接收資訊
    char *ip = inet_ntoa(caddr.sin_addr);
    printf("clent (%s) :\n%s\n",ip,buf );
    close(sockefd);
}