基於UDP的服務器和客戶端之間的通訊

1、socket 網絡套接字linux

建立
函數原型:
int socket(int domain, int type, int protocol);
參數說明: 
domain:協議域,又稱協議族(family)。經常使用的協議族有AF_INET、AF_INET六、AF_LOCAL(或稱AF_UNIX,Unix域Socket)、AF_ROUTE等。協議族決定了socket的地址類型,在通訊中必須採用對應的地址,如AF_INET決定了要用ipv4地址(32位的)與端口號(16位的)的組合、AF_UNIX決定了要用一個絕對路徑名做爲地址。
type:指定Socket類型。經常使用的socket類型有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。流式Socket(SOCK_STREAM)是一種面向鏈接的Socket,針對於面向鏈接的TCP服務應用。數據報式Socket(SOCK_DGRAM)是一種無鏈接的Socket,對應於無鏈接的UDP服務應用。
protocol:指定協議。經常使用協議有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,分別對應TCP傳輸協議、UDP傳輸協議、STCP傳輸協議、TIPC傳輸協議。
注意:1.type和protocol不能夠隨意組合,如SOCK_STREAM不能夠跟IPPROTO_UDP組合。當第三個參數爲0時,會自動選擇第二個參數類型對應的默認協議。
2.WindowsSocket下protocol參數中不存在IPPROTO_STCP
2、sockaddr_in 
sockaddr_in(在netinet/in.h中定義):
1
2
3
4
5
6
7
8
9
10
11
12
13
struct sockaddr_in
 
{
 
short sin_family;/*Address family通常來講AF_INET(地址族)PF_INET(協議族)*/
 
unsigned short sin_port;/*Port number(必需要採用網絡數據格式,普通數字能夠用htons()函數轉換成網絡數據格式的數字)*/
 
struct in_addr sin_addr;/*IP address in network byte order(Internet address)*/
 
unsigned char sin_zero[8];/*Same size as struct sockaddr沒有實際意義,只是爲了 跟SOCKADDR結構在內存中對齊*/
 
};
in_addr結構
1
2
3
4
5
typedef uint32_t in_addr_t;
struct in_addr
  {
    in_addr_t s_addr;
  };
sin_family指代協議族,在socket編程中只能是AF_INET
sin_port存儲端口號(使用網絡字節順序),在linux下,端口號的範圍0~65535,同時0~1024範圍的端口號已經被系統使用或保留。
sin_addr存儲IP地址,使用in_addr這個數據結構
sin_zero是爲了讓sockaddr與sockaddr_in兩個數據結構保持大小相同而保留的空字節。
s_addr按照網絡字節順序存儲IP地址
3、綁定編程

int bind(SOCKET socket, const struct sockaddr* address, socklen_t address_len);
參數說明:
socket:是一個套接字描述符。
address:是一個sockaddr結構指針,該結構中包含了要結合的地址和端口號。
address_len:肯定address緩衝區的長度。
返回值:
若是函數執行成功,返回值爲0,不然爲SOCKET_ERROR。
4、接收服務器

函數原型:
ssize_t recvfrom(int sockfd, void buf, int len, unsigned int flags, struct socketaddr* from, socket_t* fromlen);
參數說明:
sockfd:標識一個已鏈接套接口的描述字。
buf:接收數據緩衝區。
len:緩衝區長度。
flags:調用操做方式。是如下一個或者多個標誌的組合體,可經過or操做連在一塊兒:
from:(可選)指針,指向裝有源地址的緩衝區。
fromlen:(可選)指針,指向from緩衝區長度值。
5、發送網絡

函數原型:
int sendto( SOCKET s, const char FAR* buf, int size, int flags, const struct sockaddr FAR* to, int tolen);
參數說明:
s:套接字
buf:待發送數據的緩衝區
size:緩衝區長度
flags:調用方式標誌位, 通常爲0, 改變Flags,將會改變Sendto發送的形式
addr:(可選)指針,指向目的套接字的地址
tolen:addr所指地址的長度
返回值:
若是成功,則返回發送的字節數,失敗則返回SOCKET_ERROR。數據結構


服務器端代碼:dom

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>socket

int main(int argc,char *argv[])
{
        if(argc!=3)
        {
                printf("Usage ./server [ip]  [port]\n");
                return 1;
        }
        int sock=socket(AF_INET,SOCK_DGRAM,0);
        if(sock<0)
        {
                perror("socket");
                return 2;
        }函數

        struct sockaddr_in local;ui

 local.sin_family=AF_INET;//ipv4
        local.sin_port=htons(atoi(argv[2]));//主機字節序轉換爲網絡字節序
        local.sin_addr.s_addr=inet_addr(argv[1]);//字符串轉in_addr的函數.net


        if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
        {
                perror("bind");
                return 3;
        }


        char buf[1024];
        struct sockaddr_in client;
        while(1)
        {
                socklen_t len=sizeof(client);
                ssize_t s=recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&client,&len);
                if(s>0)
                {
                        buf[s]=0;

                        printf("[%s:%d]:%s\n",inet_ntoa(client.sin_addr),\

   ntohs(client.sin_port),buf);
                        sendto(sock,buf,strlen(buf),0, \
                                        (struct sockaddr*)&client,sizeof(client));
                }
        }
        close(sock);
        return 0;
}

客戶端的代碼:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

int main(int argc,char *argv[])
{
        if(argc!=3)
        {
           printf("./Usage [ip] [port]\n");
           return 1;
        }
        int sock=socket(AF_INET,SOCK_DGRAM,0);
        if(sock<0)
        {
                perror("socket");
                return 2;

        }

struct sockaddr_in server;
        server.sin_family=AF_INET;
        server.sin_port=htons(atoi(argv[2]));
        server.sin_addr.s_addr=inet_addr(argv[1]);


        char buf[1024];
        struct sockaddr_in peer;
        while(1)
        {
                socklen_t len=sizeof(peer);
                printf("Please Enter# ");
                fflush(stdout);
                ssize_t s=read(0,buf,sizeof(buf)-1);
                if(s>0)
                {
                        buf[s-1]=0;
                        sendto(sock,buf,strlen(buf),0,\
                                        (struct sockaddr*)&server,sizeof(server));
                        ssize_t _s=recvfrom(sock,buf,sizeof(buf)-1,0,\
                                        (struct sockaddr*)&peer,&len);

         if(_s>0)                         {                                 buf[_s]=0;                                 printf("server echo# %s\n",buf);                         }                 }         }         close(sock);         return 0; }

相關文章
相關標籤/搜索