TCP、UDP网络编程

文章详细介绍了TCP和UDP在网络编程中的基本概念和使用方法,包括服务器端的套接字创建、绑定、监听、接受连接以及数据收发,客户端的连接与数据发送。同时提供了TCP和UDP的C语言代码示例,展示了如何在实际操作中建立和管理连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TCP、UDP网络编程

  • 基本概念

    • TCP
      • 可靠、有重传机制、速度慢、有链接
    • UDP
      • 不可靠、速度快、无链接
  • 通信三要素

    源、目的、长度

    客户端主动地发起请求、服务器被动地响应请求

  • TCP建立传输

    • 服务器端

      1. 创建一个套接字
      #include <sys/socket.h>
      int socket(int domain, int type, int protocol);
      /*
      	domain:AF_INET、AF_INET6、AF_UNIX
      	type:SOCK_STREAM、SOCK_DGRAM
      	protocol: 0 
      	返回值:
      		成功: 新套接字所对应文件描述符
      		失败: -1 errno
       */
      
      1. 绑定地址结构
      #include <arpa/inet.h>
      int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
      /*
      	sockfd: socket 函数返回值
      	struct sockaddr_in addr;
              addr.sin_family = AF_INET;
              addr.sin_port = htons(8888);
              addr.sin_addr.s_addr = htonl(INADDR_ANY);
          addr: 传入参数(struct sockaddr *)&addr
      	addrlen: sizeof(addr) 地址结构的大小。
      	返回值:
      		成功:0
      		失败:-1 errno
      */
      
      1. 设置同时与服务器建立连接的上限数。(同时进行3次握手的客户端数量)
      int listen(int sockfd, int backlog);
      /*
      	sockfd: socket 函数返回值
      	backlog:上限数值。最大值 128.
      	返回值:
      		成功:0
      		失败:-1 errno	
      */
      
      1. 阻塞等待客户端建立连接,成功的话,返回一个与客户端成功连接的socket文件描述符。
      int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
      /*
      	sockfd: 客户端socket 函数返回值
      	addr:传出参数。成功与服务器建立连接的那个客户端的地址结构(IP+port)
      		socklen_t clit_addr_len = sizeof(addr);
      	addrlen:传入传出。 &clit_addr_len
      			 入:addr的大小。 出:客户端addr实际大小。
      	返回值:
      		成功:能与客户端进行数据通信的 socket 对应的文件描述。
      		失败: -1 , errno
      */
      
      1. 接收数据
      #include <sys/types.h>
      #include <sys/socket.h>
      ssize_t recv(int sockfd, void *buf, size_t len, int flags);
      /*
      	sockfd: 服务器端socket 函数返回值
      	buf:接收数据buffer
      	len:要接受数据的大小,buffer-1
      	flags:0
      	返回值:
      		成功:返回接收到的字节数
      		失败: -1 , errno
      */
      

      代码示例

      #include <sys/types.h>          
      #include <sys/socket.h>
      #include <stdlib.h>
      #include <stdio.h>
      #include <netinet/in.h>
      #include <string.h>
      #include <arpa/inet.h>
      #include <unistd.h>
      #include <signal.h>
      
      
      #define SERVER_PORT 8888
      #define BACKLOG     10
      
      /*
       * Socket
       * bind
       * listen
       * accept
       * send/receive
       */
      int main(int argc, char **argv)
      {
          int iSocketServer;
          int iSocketClient;
          int iRet;
          int iRecvLen;
      
          struct sockaddr_in tSocketServerAddr;
          struct sockaddr_in tSocketClientAddr;
      
          unsigned char ucRecvBuf[1000];
      
          int iClientNum = -1;
      
          signal(SIGCHLD, SIG_IGN);   /* 回收子进程 */
      
          iSocketServer =  socket(AF_INET, SOCK_STREAM, 0);
          if (-1 == iSocketServer)
          {
              printf("socket error\n");
              return -1;
          }
          tSocketServerAddr.sin_family      = AF_INET;
          tSocketServerAddr.sin_port        = htons(SERVER_PORT); //host to net short
          tSocketServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
          memset(tSocketServerAddr.sin_zero, 0, 8);
      
          iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(tSocketServerAddr));
          if (iRet == -1)
          {
              printf("bind error\n");
              return -1;
          }
      
          iRet =  listen(iSocketServer, BACKLOG);
          if (iRet == -1)
          {
              printf("listen error\n");
              return -1;
          }
      
          while(1)
          {
              socklen_t iAddrLen = sizeof(struct sockaddr);
              iSocketClient = accept(iSocketServer, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
              if (-1 != iSocketClient)
              {
                  iClientNum++;
                  printf("Get connect from client %d: %s\n", iClientNum, inet_ntoa(tSocketClientAddr.sin_addr));
                  if (!fork())
                  {
                      /* 子进程地源码 */
                      while(1)
                      {
                          /* 接收客户端发来的数据并显示出来 */
                          iRecvLen = recv(iSocketClient, ucRecvBuf, 999, 0);
                          if (iRecvLen <= 0)
                          {
                              close(iSocketClient);
                              return -1;
                          }
                          else
                          {
                              ucRecvBuf[iRecvLen] = '\0';
                              printf("Get message from client %d: %s", iClientNum, ucRecvBuf);
                          }
                      }
                  }
              }
          }
          close(iSocketServer);
          return 0;
      }
      
    • 客户端

      1. 创建socket

      2. 与服务器建立连接

      int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
      /*
      	sockfd: socket 函数返回值
      	struct sockaddr_in srv_addr;		// 服务器地址结构
      		srv_addr.sin_family = AF_INET;
      		srv_addr.sin_port = 9527 	跟服务器bind时设定的 port 完全一致。
      		inet_pton(AF_INET, "服务器的IP地址",&srv_adrr.sin_addr.s_addr);
      	addr:传入参数。服务器的地址结构	
      	addrlen:服务器的地址结构的大小
      	返回值:
      		成功:0
      		失败:-1 errno
      */
      
      1. 发送数据
      #include <sys/types.h>
      #include <sys/socket.h>
      ssize_t send(int sockfd, const void *buf, size_t len, int flags);
      /*
      	sockfd:客户端socket 函数返回值
      	buf:发送数据的buffer
      	len:实际发送的字节数strlen(buf)
      	flags:0
      */
      

      代码示例

      #include <sys/types.h>          
      #include <sys/socket.h>
      #include <stdlib.h>
      #include <stdio.h>
      #include <netinet/in.h>
      #include <string.h>
      #include <arpa/inet.h>
      #include <unistd.h>
      
      #define SERVER_PORT 8888
      
      /*
       *socket
       *connect
       *send
       */
      
      int main(int argc, char **argv)
      {
          int iSocketClient;
          int iRet;
          int iSendLen;
      
          struct sockaddr_in tSocketServerAddr;
          unsigned char ucSendBuf[1000];
      
          if (argc != 2)
          {
              printf("Usage:\n");
              printf("%s <server_ip>\n", argv[0]);
              return -1;
          }
          iSocketClient = socket(AF_INET, SOCK_STREAM, 0);
          if (-1 == iSocketClient)
          {
              printf("socket error\n");
              return -1;
          }
      
          tSocketServerAddr.sin_family      = AF_INET;
          tSocketServerAddr.sin_port        = htons(SERVER_PORT); //host to net short
          //tSocketServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
          if(0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))
          {
              printf("invalid server_ip\n");
              return -1;
          }
      
      
          iRet =  connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
          if (-1 == iSocketClient)
          {
              printf("connect error\n");
              return -1;
          }
          while (1)
          {
              if (fgets(ucSendBuf, 999, stdin))
              {
                  iSendLen = send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0);
                  if (iSendLen <= 0)
                  {
                      close(iSocketClient);
                      return -1;
                  }
              }
          }
          return 0;
      }
      
  • UDP建立传输

    • 服务器端

      1. 创建socket

      2. 绑定地址结构

      3. recvfrom

        ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                                struct sockaddr *src_addr, socklen_t *addrlen);
        
        /*
        	sockfd: 服务端socket 函数返回值
        	buf:接收数据buffer
        	len:要接受数据的大小,buffer-1
        	flags:0
        	src_addr:客户端的地址结构
        	addrlen:地址结构大小
        	返回值:
        		成功:返回接收到的字节数
        		失败: -1 , errno
        */
        

        代码示例

        #include <sys/types.h>          
        #include <sys/socket.h>
        #include <stdlib.h>
        #include <stdio.h>
        #include <netinet/in.h>
        #include <string.h>
        #include <arpa/inet.h>
        #include <unistd.h>
        
        
        #define SERVER_PORT 8888
        #define BACKLOG     10
        
        /*
         * Socket
         * bind
         * sendto/recvfrom
         */
        int main(int argc, char **argv)
        {
            int iSocketServer;
            int iSocketClient;
            int iRet;
            int iRecvLen;
            int iAddrLen;
        
            struct sockaddr_in tSocketServerAddr;
            struct sockaddr_in tSocketClientAddr;
        
            unsigned char ucRecvBuf[1000];
        
            int iClientNum = -1;
        
        
            iSocketServer =  socket(AF_INET, SOCK_DGRAM, 0);
            if (-1 == iSocketServer)
            {
                printf("socket error\n");
                return -1;
            }
            tSocketServerAddr.sin_family      = AF_INET;
            tSocketServerAddr.sin_port        = htons(SERVER_PORT); //host to net short
            tSocketServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
            memset(tSocketServerAddr.sin_zero, 0, 8);
        
            iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(tSocketServerAddr));
            if (iRet == -1)
            {
                printf("bind error\n");
                return -1;
            }
        
        
            while(1)
            {
                iAddrLen = sizeof(struct sockaddr);
                iRecvLen = recvfrom(iSocketServer, ucRecvBuf, 999, 0,
                                (struct sockaddr*)&tSocketClientAddr, &iAddrLen);
                if (iRecvLen > 0)
                {
                    ucRecvBuf[iRecvLen] = '\0';
                    printf("Get message from %s : %s", inet_ntoa(tSocketClientAddr.sin_addr), ucRecvBuf);
                }
            }
            close(iSocketServer);
            return 0;
        }
        
    • 客户端

      1. 创建socket

      2. sendto

        ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                              const struct sockaddr *dest_addr, socklen_t addrlen);
        /*
        	sockfd:客户端socket 函数返回值
        	buf:发送数据的buffer
        	len:实际发送的字节数strlen(buf)
        	flags:0
        	dest_addr:送达的服务器端地址结构
        	addrlen:地址结构大小
        */
        

        代码示例

        #include <sys/types.h>          
        #include <sys/socket.h>
        #include <stdlib.h>
        #include <stdio.h>
        #include <netinet/in.h>
        #include <string.h>
        #include <arpa/inet.h>
        #include <unistd.h>
        
        #define SERVER_PORT 8888
        
        /*
         *socket
         *sendto
         */
        
        int main(int argc, char **argv)
        {
            int iSocketClient;
            int iRet;
            int iSendLen;
            int iAddrLen;
        
        
            struct sockaddr_in tSocketServerAddr;
            unsigned char ucSendBuf[1000];
        
            if (argc != 2)
            {
                printf("Usage:\n");
                printf("%s <server_ip>\n", argv[0]);
                return -1;
            }
            iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);
            if (-1 == iSocketClient)
            {
                printf("socket error\n");
                return -1;
            }
        
            tSocketServerAddr.sin_family      = AF_INET;
            tSocketServerAddr.sin_port        = htons(SERVER_PORT); //host to net short
            //tSocketServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
            if(0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))
            {
                printf("invalid server_ip\n");
                return -1;
            }
        
        
            while (1)
            {
                if(fgets(ucSendBuf, 999, stdin))
                {
                    iAddrLen = sizeof(struct sockaddr);
                    iSendLen = sendto(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0,
                              (const struct sockaddr*)&tSocketServerAddr, iAddrLen);
                    if (iSendLen <= 0)
                    {
                        close(iSocketClient);
                        return -1;
                    }
                }
                }
            return 0;
        }
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值