日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C Socket通信编程

發布時間:2024/8/26 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C Socket通信编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

1、socket概述

2、地址及順序處理

3、函數介紹

4、使用實例


1、socket概述

  1、TCP協議通過三次握手協議建立連接

TCP協議通過三個報文段完成連接的建立,這個過程稱為三次握手(three-way handshake),過程如下圖所示。

?

第一次握手:建立連接時,客戶端發送syn包(syn=j)到服務器,并進入SYN_SEND狀態,等待服務器確認;SYN:同步序列編號(Synchronize Sequence Numbers)。

第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。
一個完整的三次握手也就是:?請求---應答---再次確認。

對應的函數接口:
?? ? ??

?

從圖中可以看出,當客戶端調用connect時,觸發了連接請求,向服務器發送了SYN J包,這時connect進入阻塞狀態;服務器監聽到連接請求,即收到SYN J包,調用accept函數接收請求向客戶端發送SYN K ,ACK J+1,這時accept進入阻塞狀態;客戶端收到服務器的SYN K ,ACK J+1之后,這時connect返回,并對SYN K進行確認;服務器收到ACK K+1時,accept返回,至此三次握手完畢,連接建立。

  2、編程流程

2、地址及順序處理

  1、地址結構相關處理

    struct socketaddr{

      unsigned short sa_family;

      char sa_data[14]

    }

    struct socketaddr_in{

      short int sa_family;//地址族,即使用什么樣的地址,IPV4或者是IPV6

      unsigned short int sin_port;

      struct in_addr sin_addr;//存放IP地址

      unsigned char sin_zero[8]//填充0以保持也struct socketaddr 同樣大小

    }

  2、數據存儲優先順序

    網絡地址和主機地址轉換

    #include <netinet/in.h>

    uint16_t htons(uint16_t host16bit)//主機地址向網絡地址轉換

    uint32_t htols(uint32_t host32bit)

    uint16_t ntohs(uint16_t net16bit)//網絡地址向主機地址轉換

    uint32_t ntohl(uint32_t net32bit)

    成功:返回要轉換的字節序

    出錯:-1

  3、地址格式轉換

    將十進制表示的地址轉換成二進制

    #include <arpa/inet.h>

    int inet_pton(int family,//協議類型

          const char *strptr,//要轉化的值

          void *addrptr)//轉化后的地址

    int inet_ntop(int family

           void *addrptr

           char *strptr

           size_t len)//轉化后值的大小

    成功:0

    出錯:-1

  4、名字地址轉換

    gethostbyname()將主機名轉換為IP地址

    gethostbyaddr()將IP地址轉換為主機名

    #include <netbd.h>

    struct hostnet *gethostbyname(const char *honstname)

    成功:hostnet類型指針

    出錯:-1

    int getaddrinfo(const char *hostname

            const char *service 

            const struct addrinfo *hints

            struct addrinfo **result)//返回的結果

    成功:0

    出錯:-1

    struct hostnet {

      char *h_name;//主機名

      char **h_aliases;

      int h_addrtype;

      int h_length;

      char **h_addr_list;//指向IPV4的地址指針數組

    }


?

3、函數介紹  

    1、socket()  

      #include<sys/socket.h>

      int socket(int family,int type,int protocal)

      成功:非法套接字描述符

      出錯:-1;

    2、bind()

      #include<sys/socket.h>

      int bind(int sockefd,struct sockaddr *my_addr,int addrlen);

      成功:0;

      出錯:-1

    3、listen()

      #include<sys/socket.h>

      int listen(int sockfd,int backlog)

    4、accept()

      #include<sys/socket.h>

      int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);

    5、connect()

      #include<sys/socket.h>

      int connect(int sockfd,struct sockaddr *serv_addr,int addrlen);

      成功:0

      出錯:-1

    6、send()

      int send(int sockfd,const void *msg,int len,int flags)

      成功:發送的字節數

     出錯:-1

    7、recv()

      int recv(int sockfd,void *buff,int len,unsigned int flags)

      成功:接受的字節數

      出錯:-1

    8、sendto()

      int sendto(int sockfd ,const void *msg,int len,unsigned int flags,struct sockaddr *to ,int * tolen)   

      成功:發送的字節數

      出錯:-1

    9、recvfrom()

      int recvfrom(int sockfd ,const void *msg,int len,unsigned int flags,struct sockaddr *from ,int * tolen)   

      成功:接受的字節數

      出錯:-1

?


?

?

4、簡單實例

?

  • /*?File?Name:?server.c?*/??
  • #include<stdio.h>??
  • #include<stdlib.h>??
  • #include<string.h>??
  • #include<errno.h>??
  • #include<sys/types.h>??
  • #include<sys/socket.h>??
  • #include<netinet/in.h>??
  • #define?DEFAULT_PORT?8000??
  • #define?MAXLINE?4096??
  • int?main(int?argc,?char**?argv)??
  • {??
  • ????int????socket_fd,?connect_fd;??
  • ????struct?sockaddr_in?????servaddr;??
  • ????char????buff[4096];??
  • ????int?????n;??
  • ????//初始化Socket??
  • ????if(?(socket_fd?=?socket(AF_INET,?SOCK_STREAM,?0))?==?-1?){??
  • ????printf("create?socket?error:?%s(errno:?%d)\n",strerror(errno),errno);??
  • ????exit(0);??
  • ????}??
  • ????//初始化??
  • ????memset(&servaddr,?0,?sizeof(servaddr));??
  • ????servaddr.sin_family?=?AF_INET;??
  • ????servaddr.sin_addr.s_addr?=?htonl(INADDR_ANY);//IP地址設置成INADDR_ANY,讓系統自動獲取本機的IP地址。??
  • ????servaddr.sin_port?=?htons(DEFAULT_PORT);//設置的端口為DEFAULT_PORT??
  • ??
  • ????//將本地地址綁定到所創建的套接字上??
  • ????if(?bind(socket_fd,?(struct?sockaddr*)&servaddr,?sizeof(servaddr))?==?-1){??
  • ????printf("bind?socket?error:?%s(errno:?%d)\n",strerror(errno),errno);??
  • ????exit(0);??
  • ????}??
  • ????//開始監聽是否有客戶端連接??
  • ????if(?listen(socket_fd,?10)?==?-1){??
  • ????printf("listen?socket?error:?%s(errno:?%d)\n",strerror(errno),errno);??
  • ????exit(0);??
  • ????}??
  • ????printf("======waiting?for?client's?request======\n");??
  • ????while(1){??
  • //阻塞直到有客戶端連接,不然多浪費CPU資源。??
  • ????????if(?(connect_fd?=?accept(socket_fd,?(struct?sockaddr*)NULL,?NULL))?==?-1){??
  • ????????printf("accept?socket?error:?%s(errno:?%d)",strerror(errno),errno);??
  • ????????continue;??
  • ????}??
  • //接受客戶端傳過來的數據??
  • ????n?=?recv(connect_fd,?buff,?MAXLINE,?0);??
  • //向客戶端發送回應數據??
  • ????if(!fork()){?/*紫禁城*/??
  • ????????if(send(connect_fd,?"Hello,you?are?connected!\n",?26,0)?==?-1)??
  • ????????perror("send?error");??
  • ????????close(connect_fd);??
  • ????????exit(0);??
  • ????}??
  • ????buff[n]?=?'\0';??
  • ????printf("recv?msg?from?client:?%s\n",?buff);??
  • ????close(connect_fd);??
  • ????}??
  • ????close(socket_fd);??
  • }??
  • ?

    ?

    客戶端:

    ?

  • /*?File?Name:?client.c?*/??
  • ??
  • #include<stdio.h>??
  • #include<stdlib.h>??
  • #include<string.h>??
  • #include<errno.h>??
  • #include<sys/types.h>??
  • #include<sys/socket.h>??
  • #include<netinet/in.h>??
  • ??
  • #define?MAXLINE?4096??
  • ??
  • ??
  • int?main(int?argc,?char**?argv)??
  • {??
  • ????int????sockfd,?n,rec_len;??
  • ????char????recvline[4096],?sendline[4096];??
  • ????char????buf[MAXLINE];??
  • ????struct?sockaddr_in????servaddr;??
  • ??
  • ??
  • ????if(?argc?!=?2){??
  • ????printf("usage:?./client?<ipaddress>\n");??
  • ????exit(0);??
  • ????}??
  • ??
  • ??
  • ????if(?(sockfd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0){??
  • ????printf("create?socket?error:?%s(errno:?%d)\n",?strerror(errno),errno);??
  • ????exit(0);??
  • ????}??
  • ??
  • ??
  • ????memset(&servaddr,?0,?sizeof(servaddr));??
  • ????servaddr.sin_family?=?AF_INET;??
  • ????servaddr.sin_port?=?htons(8000);??
  • ????if(?inet_pton(AF_INET,?argv[1],?&servaddr.sin_addr)?<=?0){??
  • ????printf("inet_pton?error?for?%s\n",argv[1]);??
  • ????exit(0);??
  • ????}??
  • ??
  • ??
  • ????if(?connect(sockfd,?(struct?sockaddr*)&servaddr,?sizeof(servaddr))?<?0){??
  • ????printf("connect?error:?%s(errno:?%d)\n",strerror(errno),errno);??
  • ????exit(0);??
  • ????}??
  • ??
  • ??
  • ????printf("send?msg?to?server:?\n");??
  • ????fgets(sendline,?4096,?stdin);??
  • ????if(?send(sockfd,?sendline,?strlen(sendline),?0)?<?0)??
  • ????{??
  • ????printf("send?msg?error:?%s(errno:?%d)\n",?strerror(errno),?errno);??
  • ????exit(0);??
  • ????}??
  • ????if((rec_len?=?recv(sockfd,?buf,?MAXLINE,0))?==?-1)?{??
  • ???????perror("recv?error");??
  • ???????exit(1);??
  • ????}??
  • ????buf[rec_len]??=?'\0';??
  • ????printf("Received?:?%s?",buf);??
  • ????close(sockfd);??
  • ????exit(0);??
  • } ?
  • 測試:

    編譯server.c

    gcc -o server server.c

    啟動進程:

    ./server

    顯示結果:

    ======waiting for client's request======

    并等待客戶端連接。

    編譯 client.c

    gcc -o client server.c

    客戶端去連接server:

    ./client 127.0.0.1?

    等待輸入消息

    發送一條消息,輸入:c++

    此時服務器端看到:

    客戶端收到消息:

    ?

    其實可以不用client,可以使用telnet來測試:

    telnet 127.0.0.1 8000

    ?

    轉載于:https://www.cnblogs.com/void0/p/4233238.html

    總結

    以上是生活随笔為你收集整理的C Socket通信编程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。