网络编程:TCP

[复制链接]
发表于 2026-2-24 02:39:43 | 显示全部楼层 |阅读模式
一、tcp编程


留意

1.数据自己有次序
2.发送和吸收次数不必要对应
3. 


 1.  C/S 模式 

==》服务器/客户端模子
server:socket()-->bind()--->listen()-->accept()-->recv()-->close()
client:socket()-->connect()-->send()-->close();
int on = 1;
setsockopt(listfd, SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
2. 服务器端

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
1)socket() 

int socket(int domain, int type, int protocol);
功能:步调向内核提出创建一个基于内存的套接字形貌符
参数:domain  地点族,PF_INET == AF_INET ==>互联网步调
                                       PF_UNIX == AF_UNIX ==>单机步调
          type    套接字范例:
                SOCK_STREAM  流式套接字 ===》TCP   
                SOCK_DGRAM   用户数据报套接字===>UDP
                SOCK_RAW     原始套接字  ===》IP
          protocol 协议 ==》0 表现主动顺应应用层协议。
返回值:乐成 返回申请的套接字id
              失败  -1;
2)bind()

int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
功能:如果该函数在服务器端调用,则表现将 参数1相干的文件形貌符文件 与参数2指定的接口地点关联,用于从该接口担当数据。
           如果该函数在客户端调用,则表现要将 数据从参数1地点的形貌符中 取出 并从 参数2地点的接口装备上 发送出去。
留意:如果是客户端,则该函数可以省略,由默认接口发送数据。
参数:sockfd 之前通过socket函数创建的文件形貌符,套接字id
           my_addr 是物理接口的布局体指针。表现该接口的信息
      struct sockaddr      ////通用地点布局
      {
          u_short sa_family;  ////地点族
          char sa_data[14];   ////地点信息
      };
      转换成网络地点布局如下:
      struct _sockaddr_in    ///网络地点布局
      {
          u_short           sin_family; ////地点族
          u_short           sin_port;   ///地点端口
          struct in_addr  sin_addr;   ///地点IP
          char               sin_zero[8]; ////占位
      };
      struct in_addr
      {
          in_addr_t s_addr;
      }
      socklen_t addrlen: 参数2 的长度。
返回值:乐成  0 
              失败  -1; 
3)listen()

int listen(int sockfd, int backlog);
功能:在参数1地点的套接字id上监听等候链接。
参数:sockfd  套接字id
           backlog 答应链接的个数
返回值:乐成  0
              失败  -1;
4)accept()

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
   功能:从已经监听到的队列中取出有用的客户端链接并接入到当前程序。
   参数:sockfd 套接字id
              addr  如果该值为NULL ,表现岂论客户端是谁都接入。
                如果要获取客户端信息,则事先界说变量并传入变量地点,函数实行完毕将会将客户端
                信息存储到该变量中。
             addrlen  参数2的长度,如果参数2为NULL,则该值也为NULL;
                                                   如果参数不是NULL,&len,
                                                   肯定要写成len = sizeof(struct sockaddr);
   返回值:乐成 返回一个用于通讯的新套接字id;
                从该代码之后全部通讯都基于该id
                 失败  -1;
5)吸收函数/发送函数   

    read()/write ()   ///通用文件读写,可以操纵套接字。
    recv(,0) /send(,0)   ///TCP 常用套机字读写
    recvfrom()/sendto() ///UDP 常用套接字读写
ssize_t recv(int sockfd, void *buf, size_t len,int flags);
功能:从指定的sockfd套接字中以flags方式获取长度为len字节的数据到指定的buff内存中。
参数:sockfd  如果服务器则是accept的返回值的新fd
                       如果客户端则是socket的返回值旧fd
          buff 用来存储数据的当地内存,一样平常是数组大概动态内存。
          len 要获取的数据长度
          flags 获取数据的方式,0 表现壅闭担当
返回值:乐成 表现担当的数据长度,一样平常小于便是len
              失败  -1;
6)close()

 ===>关闭指定的套接字id;
3. 客户端

1)connect()

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
   功能:该函数固定有客户端利用,表现从当前主机向目的主机发起链接哀求。
   参数:sockfd 当地socket创建的套接子id
              addr 远程目的主机的地点信息
              addrlen 参数2的长度
   返回值:乐成 0
                 失败 -1;
2)send()

int send(int sockfd, const void *msg, size_t len, int flags);
   功能:从msg地点的内存中获取长度为len的数据以flags方式写入到sockfd对应的套接字中。
   参数:sockfd 如果是服务器则是accept的返回值新fd
                         如果是客户端则是sockfd的返回值旧fd
              msg 要发送的消息
              len 要发送的消息长度
              flags 消息的发送方式
  返回值:乐成  发送的字符长度
                失败  -1;

ser.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>          /* See NOTES */
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <netinet/ip.h>
  8. #include <string.h>
  9. #include <time.h>
  10. typedef struct sockaddr* (SA);
  11. int main(int argc, char *argv[])
  12. {
  13.    
  14.     //监听套接字
  15.     int listfd =  socket(AF_INET,SOCK_STREAM, 0);
  16.     if(-1 == listfd)
  17.     {
  18.         perror("socket");
  19.         exit(1);
  20.     }
  21.     struct sockaddr_in ser,cli;
  22.     bzero(&ser,sizeof(ser));
  23.     bzero(&cli,sizeof(cli));
  24.     ser.sin_family = AF_INET;
  25.     ser.sin_port = htons(50000);
  26.     //host to net long
  27.     ser.sin_addr.s_addr = htonl(INADDR_ANY);
  28.     int ret = bind(listfd,(SA)&ser,sizeof(ser));
  29.     if(-1 == ret)
  30.     {
  31.         perror("bind");
  32.         exit(1);
  33.     }
  34.     //同一时刻三次握手排队数
  35.     listen(listfd,3);
  36.     socklen_t  len = sizeof(cli);
  37.     //通信套接字
  38.     int conn = accept(listfd,(SA)&cli,&len);
  39.     if(-1 == conn)
  40.     {
  41.         perror("accept");
  42.         exit(1);
  43.     }
  44.     while(1)
  45.     {
  46.         char buf[512]={0};
  47.         int rd_ret = recv(conn,buf,sizeof(buf),0);
  48.         if(rd_ret<=0)
  49.         {// 0  对方断开连接 -1 错误
  50.             break;
  51.         }
  52.         time_t tm;
  53.         time(&tm);
  54.         sprintf(buf,"%s %s",buf,ctime(&tm));
  55.         send(conn,buf,strlen(buf),0);
  56.         
  57.     }
  58.     close(listfd);
  59.     close(conn);
  60.     return 0;
  61. }
复制代码
cli.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>          /* See NOTES */
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <netinet/ip.h>
  8. #include <string.h>
  9. #include <time.h>
  10. #include <arpa/inet.h>
  11. typedef struct sockaddr* (SA);
  12. int main(int argc, char *argv[])
  13. {
  14.     int sockfd = socket(AF_INET,SOCK_STREAM,0);
  15.     if(-1 == sockfd)
  16.     {
  17.         perror("socket");
  18.         exit(1);
  19.     }
  20.     struct sockaddr_in ser;
  21.     bzero(&ser,sizeof(ser));
  22.     ser.sin_family = AF_INET;
  23.     ser.sin_port = htons(50000);
  24.     //host to net long
  25.     ser.sin_addr.s_addr = inet_addr("127.0.0.1");
  26.     int ret = connect(sockfd,(SA)&ser,sizeof(ser));
  27.     if(-1 == ret)
  28.     {
  29.         perror("connect");
  30.         exit(1);
  31.     }
  32.     while(1)
  33.     {
  34.         char buf[512]="hello,this is tcp test";
  35.         send(sockfd,buf,strlen(buf),0);
  36.         bzero(buf,sizeof(buf));
  37.         recv(sockfd,buf,sizeof(buf),0);
  38.         printf("buf :%s\n",buf);
  39.         sleep(1);
  40.     }
  41.     close(sockfd);
  42.     return 0;
  43. }
复制代码


 tcp发文件,图片——cp 1.png 2.png
ser.c 
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>          /* See NOTES */
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <netinet/ip.h>
  8. #include <string.h>
  9. #include <time.h>
  10. #include <fcntl.h>
  11. typedef struct sockaddr* (SA);
  12. int main(int argc, char *argv[])
  13. {
  14.    
  15.     //监听套接字
  16.     int listfd =  socket(AF_INET,SOCK_STREAM, 0);
  17.     if(-1 == listfd)
  18.     {
  19.         perror("socket");
  20.         exit(1);
  21.     }
  22.     struct sockaddr_in ser,cli;
  23.     bzero(&ser,sizeof(ser));
  24.     bzero(&cli,sizeof(cli));
  25.     ser.sin_family = AF_INET;
  26.     ser.sin_port = htons(50000);
  27.     //host to net long
  28.     ser.sin_addr.s_addr = htonl(INADDR_ANY);
  29.     int ret = bind(listfd,(SA)&ser,sizeof(ser));
  30.     if(-1 == ret)
  31.     {
  32.         perror("bind");
  33.         exit(1);
  34.     }
  35.     //同一时刻三次握手排队数
  36.     listen(listfd,3);
  37.     socklen_t  len = sizeof(cli);
  38.     //通信套接字
  39.     int conn = accept(listfd,(SA)&cli,&len);
  40.     if(-1 == conn)
  41.     {
  42.         perror("accept");
  43.         exit(1);
  44.     }
  45.     int fd = open("2.png",O_WRONLY|O_CREAT|O_TRUNC,0666);
  46.     if(-1 ==fd)
  47.     {
  48.         perror("open");
  49.         exit(1);
  50.     }
  51.     while(1)
  52.     {
  53.         char buf[512]={0};
  54.         int rd_ret = recv(conn,buf,sizeof(buf),0);
  55.         if(rd_ret<=0)
  56.         {// 0  对方断开连接 -1 错误
  57.             break;
  58.         }
  59.         write(fd,buf,rd_ret);
  60.         bzero(buf,sizeof(buf));
  61.         strcpy(buf,"123");
  62.         send(conn,buf,strlen(buf),0);
  63.         
  64.     }
  65.     close(fd);
  66.     close(listfd);
  67.     close(conn);
  68.     return 0;
  69. }
复制代码
cli.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>          /* See NOTES */
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <netinet/ip.h>
  8. #include <string.h>
  9. #include <time.h>
  10. #include <arpa/inet.h>
  11. #include <fcntl.h>
  12. typedef struct sockaddr* (SA);
  13. int main(int argc, char *argv[])
  14. {
  15.     int sockfd = socket(AF_INET,SOCK_STREAM,0);
  16.     if(-1 == sockfd)
  17.     {
  18.         perror("socket");
  19.         exit(1);
  20.     }
  21.     struct sockaddr_in ser;
  22.     bzero(&ser,sizeof(ser));
  23.     ser.sin_family = AF_INET;
  24.     ser.sin_port = htons(50000);
  25.     //host to net long
  26.     ser.sin_addr.s_addr = inet_addr("127.0.0.1");
  27.     int ret = connect(sockfd,(SA)&ser,sizeof(ser));
  28.     if(-1 == ret)
  29.     {
  30.         perror("connect");
  31.         exit(1);
  32.     }
  33.     int fd = open("/home/linux/1.png",O_RDONLY);
  34.     if(-1 ==fd)
  35.     {
  36.         perror("open");
  37.         exit(1);
  38.     }
  39.     while(1)
  40.     {
  41.         char buf[512]={0};
  42.         int rd_ret = read(fd,buf,sizeof(buf));
  43.         if(rd_ret<=0)
  44.         {
  45.             break;
  46.         }
  47.         send(sockfd,buf,rd_ret,0);
  48.         bzero(buf,sizeof(buf));
  49.         recv(sockfd,buf,sizeof(buf),0);
  50.     }
  51.     close(fd);
  52.     close(sockfd);
  53.     return 0;
  54. }
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表