网络编程:TCP
创始人
2025-01-11 12:06:57
0次

一、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          /* See NOTES */
#include

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

#include  #include  #include  #include           /* See NOTES */ #include  #include  #include  #include  #include  typedef struct sockaddr* (SA); int main(int argc, char *argv[]) {         //监听套接字     int listfd =  socket(AF_INET,SOCK_STREAM, 0);     if(-1 == listfd)     {         perror("socket");         exit(1);     }      struct sockaddr_in ser,cli;     bzero(&ser,sizeof(ser));     bzero(&cli,sizeof(cli));     ser.sin_family = AF_INET;     ser.sin_port = htons(50000);     //host to net long      ser.sin_addr.s_addr = htonl(INADDR_ANY);      int ret = bind(listfd,(SA)&ser,sizeof(ser));     if(-1 == ret)     {         perror("bind");         exit(1);     }     //同一时刻三次握手排队数     listen(listfd,3);     socklen_t  len = sizeof(cli);     //通信套接字      int conn = accept(listfd,(SA)&cli,&len);     if(-1 == conn)     {         perror("accept");         exit(1);     }      while(1)     {         char buf[512]={0};         int rd_ret = recv(conn,buf,sizeof(buf),0);         if(rd_ret<=0)         {// 0  对方断开连接 -1 错误             break;         }         time_t tm;         time(&tm);         sprintf(buf,"%s %s",buf,ctime(&tm));         send(conn,buf,strlen(buf),0);              }     close(listfd);     close(conn);     return 0; }

cli.c

#include  #include  #include  #include           /* See NOTES */ #include  #include  #include  #include  #include  #include  typedef struct sockaddr* (SA);  int main(int argc, char *argv[]) {     int sockfd = socket(AF_INET,SOCK_STREAM,0);     if(-1 == sockfd)     {         perror("socket");         exit(1);     }     struct sockaddr_in ser;     bzero(&ser,sizeof(ser));     ser.sin_family = AF_INET;     ser.sin_port = htons(50000);     //host to net long      ser.sin_addr.s_addr = inet_addr("127.0.0.1");      int ret = connect(sockfd,(SA)&ser,sizeof(ser));     if(-1 == ret)     {         perror("connect");         exit(1);     }     while(1)     {         char buf[512]="hello,this is tcp test";         send(sockfd,buf,strlen(buf),0);         bzero(buf,sizeof(buf));         recv(sockfd,buf,sizeof(buf),0);         printf("buf :%s\n",buf);         sleep(1);     }     close(sockfd);     return 0; }


 tcp发文件,图片——cp 1.png 2.png

ser.c 

#include  #include  #include  #include           /* See NOTES */ #include  #include  #include  #include  #include  #include  typedef struct sockaddr* (SA); int main(int argc, char *argv[]) {         //监听套接字     int listfd =  socket(AF_INET,SOCK_STREAM, 0);     if(-1 == listfd)     {         perror("socket");         exit(1);     }      struct sockaddr_in ser,cli;     bzero(&ser,sizeof(ser));     bzero(&cli,sizeof(cli));     ser.sin_family = AF_INET;     ser.sin_port = htons(50000);     //host to net long      ser.sin_addr.s_addr = htonl(INADDR_ANY);      int ret = bind(listfd,(SA)&ser,sizeof(ser));     if(-1 == ret)     {         perror("bind");         exit(1);     }     //同一时刻三次握手排队数     listen(listfd,3);     socklen_t  len = sizeof(cli);     //通信套接字      int conn = accept(listfd,(SA)&cli,&len);     if(-1 == conn)     {         perror("accept");         exit(1);     }     int fd = open("2.png",O_WRONLY|O_CREAT|O_TRUNC,0666);     if(-1 ==fd)     {         perror("open");         exit(1);     }     while(1)     {         char buf[512]={0};         int rd_ret = recv(conn,buf,sizeof(buf),0);         if(rd_ret<=0)         {// 0  对方断开连接 -1 错误             break;         }         write(fd,buf,rd_ret);         bzero(buf,sizeof(buf));          strcpy(buf,"123");         send(conn,buf,strlen(buf),0);              }     close(fd);     close(listfd);     close(conn);     return 0; }

cli.c

#include  #include  #include  #include           /* See NOTES */ #include  #include  #include  #include  #include  #include  #include  typedef struct sockaddr* (SA);  int main(int argc, char *argv[]) {     int sockfd = socket(AF_INET,SOCK_STREAM,0);     if(-1 == sockfd)     {         perror("socket");         exit(1);     }     struct sockaddr_in ser;     bzero(&ser,sizeof(ser));     ser.sin_family = AF_INET;     ser.sin_port = htons(50000);     //host to net long      ser.sin_addr.s_addr = inet_addr("127.0.0.1");      int ret = connect(sockfd,(SA)&ser,sizeof(ser));     if(-1 == ret)     {         perror("connect");         exit(1);     }     int fd = open("/home/linux/1.png",O_RDONLY);     if(-1 ==fd)     {         perror("open");         exit(1);     }     while(1)     {         char buf[512]={0};         int rd_ret = read(fd,buf,sizeof(buf));         if(rd_ret<=0)         {             break;         }         send(sockfd,buf,rd_ret,0);         bzero(buf,sizeof(buf));         recv(sockfd,buf,sizeof(buf),0);     }     close(fd);     close(sockfd);     return 0; }

相关内容

热门资讯

实测交流透视挂!宝玛大厅ai智... 实测交流透视挂!宝玛大厅ai智能透视挂教程,宝玛大厅破解软件经验(本来有挂辅助)1、每一步都需要思考...
总算了解辅助器!朱雀吴江三缺一... 总算了解辅助器!朱雀吴江三缺一ai智能透视辅助挂技巧,朱雀吴江三缺一好像是有挂(有辅助挂细节)朱雀吴...
今日公布透视!九五至尊大厅ai... 今日公布透视!九五至尊大厅ai智能透视插件,九五至尊大厅有没有透视挂窍门(切实有挂技术)1、在九五至...
玩家必看科普开挂!聚闲麻将ai... 玩家必看科普开挂!聚闲麻将ai智能透视辅助挂软件,聚闲麻将总是真的有挂(有辅助挂方式)聚闲麻将能透视...
据报道开挂!旅游娱乐ai智能开... 据报道开挂!旅游娱乐ai智能开挂工具,旅游娱乐辅助工具演示(一直有挂教学)1、全新机制【旅游娱乐ai...
一分钟揭秘开挂!决胜朋来麻将a... 一分钟揭秘开挂!决胜朋来麻将ai智能透视辅助挂教程,决胜朋来麻将真是真的是有挂(有辅助挂总结)1、首...
如何分辨真伪透视!红牛ai智能... 如何分辨真伪透视!红牛ai智能透视攻略,红牛是不是有挂经验(真是有挂技术)1、操作简单,无需红牛手机...
2分钟细说辅助器!江湖大庆麻将... 2分钟细说辅助器!江湖大庆麻将ai智能透视辅助挂攻略,江湖大庆麻将竟然是真的有挂(有辅助挂头条)1、...
总算清楚透视挂!老夫子厅ai智... 总算清楚透视挂!老夫子厅ai智能透视挂技巧,老夫子厅怎么开挂课程(好像发现有挂)老夫子厅破解侠是真的...
解密关于辅助!菜鸟麻将ai智能... 解密关于辅助!菜鸟麻将ai智能透视辅助挂脚本,菜鸟麻将总是存在有挂(有辅助挂存在)1、用户打开应用后...