天天看點

Linux下無連接配接的套接字通信C實作

不得不說。。。自己懶的程度連自己都受不了。。。雖然一直在學~但處于學完又忘的狀态。。。總覺得自己記完筆記又會忘掉。。。555。。。

自己正在慢慢挖掘linux下程式設計的興趣,感覺處于混沌狀态,都說程式設計這種東西都得有興趣才可以編出來的~~希望我對它的興趣會一直上升~~~

好好記錄筆記。。。

無連接配接的套接字通信即UDP通信~C的實作看起來和java的代碼實作差不少額。。。但總的來說,步驟都差不多。。。flashplayer版本太低了,找天補"21天linux'的圖~

補上:

Linux下無連接配接的套接字通信C實作

具體說法:

伺服器:1.建立socket;    2.socket綁定端口;    3.讀取接收到的資訊;    4.發送消息

               socket()            bind()                    recvfrom()                sendto()

用戶端:1.建立socket;    2.連接配接一個指定的計算機和端口;    3.發送消息;    4.讀取接收到的資訊

               socket()            bind()                                        sendto()        recvfrom()

伺服器源碼:

#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#define LOCALPORT 4567
                                                                                                                                                                                                        
int main(int argc, char *argv[])
{
    int mysock, len;
    struct sockaddr_in addr;
    int i = 0;
    char msg[256];
    int addr_len;
    if((mysock=socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("error");
        exit(1);
    }
    else
    {
        printf("socket created.\n");
        printf("socket id: %d\n",mysock);
    }
    addr_len = sizeof(struct sockaddr_in);
    bzero(&addr, sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(LOCALPORT);
    addr.sin_addr.s_addr=htonl(INADDR_ANY);//0.0.0.0任意位址
    if(bind(mysock, &addr, sizeof(addr)) < 0)
    {
        perror("connect");
        exit(1);
    }
    else
    {
        printf("bind ok.\n");
        printf("local port : %d\n",LOCALPORT);
    }
    while(1)
    {
        bzero(msg,sizeof(msg));
        /*接收到的資訊*/
        len=recvfrom(mysock,msg,sizeof(msg),0,&addr,&addr_len);
        printf("%d :",i);
        i++;
        printf("msg from: %s\n",inet_ntoa(addr.sin_addr));
        printf(" msg len: %d\n",len);
        printf(" msg: %s\n",msg);
        sendto(mysock,msg,len,0,&addr,addr_len);
        /*以上将字元串傳回給用戶端*/
    }
    return 0;
}      

知識點補充:

套接字=傳輸層協定+端口号+IP位址

套接字相關類型:sockaddr或sockaddr_in

struct sockaddr//系統中定義好的
{
    unsigned short int sa_family;
    char sa_data[14];
};      

sa_family:指定通信的位址類型。如果是TCP/IP通信,則為AF_INET

sa_data:最多14個字元長度,用來儲存IP位址和端口資訊

struct socketaddr_in
{
    unsigned short int sin_family;
    uint16_t sin_port;
    struct in_addr sin_addr;
    unsigned char sin_zero[8];
};
struct in addr
{
    uint32_t s_addr;//儲存一個IP位址
};      

sin_family和sa_family相同

sin_port:套接字使用的端口号

sin_addr:需要通路的IP位址

sin_zero:未使用的字段,填充為0

好的~接下來開始看代碼(至于什麼時候導入什麼包需要另開blog記下來才可以!)

socket(AF_INET, SOCK_DGRAM, 0)建立socket并将傳回号碼到mysock,建立成功後,注意套接字放到addr中,bzero(&addr,sizeof(addr))-->bzero(void *s, int n)功能:置位元組字元串s的前n個位元組為零且包括‘\0’。建議改成memset()函數作初始化。初始化addr的各項參數,參考struct socketaddr_in;通過bind(mysock,&addr,sizeof(addr))綁定端口;然後就可以等待用戶端給伺服器端發送消息了~~

while循環一直等待用戶端發送消息,recvfrom(mysock,msg,sizeof(msg),0,&addr,&addr_len)負責接收消息,接收的長度放到len中。inet_ntoa(addr.sin_addr)将一個IP轉換成一個網際網路标準點分格式的字元串,sendto(mysock,msg,len,0,&addr,addr_len)将字元串傳回給用戶端。

接下來是用戶端的代碼:

#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#define REMOTEPORT 4567
#define REMOTEIP "127.0.0.1"
int main(int argc, char *argv[])
{
    int s,len;
    struct sockaddr_in addr;//套接字結構體
    int addr_len;
    char msg[256];
    int i = 0;
    if((s=socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("error");
        exit(1);
    }
    else
    {
        printf("socket created.\n");
        printf("socket id:%d\n",s);
        printf("remote ip:%s\n",REMOTEIP);
        printf("remote port:%d\n",REMOTEPORT);
    }
    addr_len=sizeof(struct sockaddr_in);
    bzero(&addr, sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(REMOTEPORT);
    addr.sin_addr.s_addr=inet_addr(REMOTEIP);//struct in_addr sin_addr
    while(1)
    {
        bzero(msg,sizeof(msg));
        len = read(STDIN_FILENO, msg, sizeof(msg));
        /*s是建立好的socket,msg是發送的字元串,len是字元長度,flag=0*/
        sendto(s,msg,len,0,&addr,addr_len);
        printf("\nInput message: %s\n",msg);
        /*這是接受到的資訊*/
        len = recvfrom(s,msg,sizeof(msg),0,&addr,&addr_len);
        printf("%d: ",i);
        i++;
        printf("Received message: %s\n",msg);/*這是伺服器傳回的資訊*/
    }
    return 0;
}      

解釋一下和上面有差異和沒解析的部分~

htonl:将計算機中的32位長整型數轉換成網絡字元順序的32位長整型數

htons:(同上,16位)

繼續閱讀