您的位置:首页 > 汽车 > 时评 > 基于UDP/TCP的 c/s 通信模型

基于UDP/TCP的 c/s 通信模型

2024/11/19 22:37:34 来源:https://blog.csdn.net/qq_69639971/article/details/141435113  浏览:    关键词:基于UDP/TCP的 c/s 通信模型

基于UDP c/s通信模型

  • 客户端(socket;sendto ...)  
  • 服务器端  ---把自己的地址公布出去 (socket;bind //绑定; recvfrom ...)

1.recvfrom函数:

 ssize_t recvfrom( int sockfd,    //socket的fd
                               void *buf,    //保存数据的一块空间的地址 
                             size_t len,    //这块空间的大小 
                               int flags,    // 0  默认的接收方式 --- 阻塞方式 
   struct sockaddr *src_addr,    //用来保存发送方的地址信息 
            socklen_t *addrlen     //表示发送方实际的地址信息大小  ); 

返回值:成功:返回接收到的字节数; 失败:-1。 

  

struct sockaddr_in srcaddr;
socklen_t addrlen = sizeof(srcaddr);char buf[1024];while(1)
{recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr *)&srcaddr,&addrlen);printf("IP = %s\n",inet_ntoa(srcaddr.sin_addr));printf("post = %d\n",ntohs(srcaddr.sin_port));printf("buf = %s\n",buf);
}

2.bind函数:

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

        (1)功能:如果该函数在服务器端调用,则表示将参数1相关的文件描述符文件与参数2 指定的接口地址关联,用于从该接口接受数据。如果该函数在客户端调用,则表示要将数据从参数1所在的描述符中取出并从参数2所在的接口设备上发送出去。

        注意:如果是客户端,则该函数可以省略,由默认接口发送数据。
        (2)参数:sockfd之前通过socket函数创建的文件描述符,套接字id; my_addr 是物理接口的结构体指针。表示该接口的信息。  

struct sockaddr      通用地址结构 --- ip + 端口 
{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  //"192.168.1.123"char               sin_zero[8]; //占位
};in_addr_t  === unsigned int 
struct in_addr
{in_addr_t s_addr;
}

练习:

           任务1 从键盘获得数据发给服务器  --fgets
           任务2 从服务器不断获取数据打印  --recvfrom 

1.客户端:
int c_fd = 0;
void child_handler(int signo)
{close(c_fd);printf("child--exit--\n");exit(0);}void father_handler(int signo)
{close(c_fd);printf("father--exit--\n");exit(0);
}int main(int argc, const char *argv[])
{//1.socket 创建通信的一端 int fd = socket(AF_INET,SOCK_DGRAM,0);if (fd < 0){perror("socket fail");return -1;}printf("fd = %d\n",fd);struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = inet_addr("192.168.1.135");char buf[1024] = {0};//区分任务 pid_t pid = fork();if (pid < 0){perror("fork fail");return -1;}if (pid > 0){signal(SIGCHLD,father_handler);c_fd = fd;while (1){printf(">");fgets(buf,sizeof(buf),stdin);int ret = sendto(fd,buf,strlen(buf)+1,0,(const struct sockaddr *)&seraddr,sizeof(seraddr));printf("ret = %d\n",ret);if (strncmp(buf,"quit",4) == 0){kill(pid,SIGUSR1);wait(NULL);close(fd);exit(0);}}}else if (pid == 0) {c_fd = fd;signal(SIGUSR1,child_handler);while (1){recvfrom(fd,buf,sizeof(buf),0,NULL,NULL);printf("buf = %s\n",buf);if (strncmp(buf,"quit",4) == 0){close(fd);exit(0);}}}//close(fd); return 0;
}
2.服务器端:       
int c_fd = 0;
void child_handler(int signo)
{close(c_fd);printf("child--exit--\n");exit(0);}void father_handler(int signo)
{close(c_fd);printf("father--exit--\n");exit(0);
}int main(int argc, const char *argv[])
{//1.socket 创建通信的一端 int fd = socket(AF_INET,SOCK_DGRAM,0);if (fd < 0){perror("socket fail");return -1;}	struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = inet_addr("192.168.1.135");//2.bindif (bind(fd,(struct sockaddr *)&seraddr,sizeof(seraddr)) < 0){perror("bind fail");return -1;}struct sockaddr_in srcaddr;socklen_t addrlen = sizeof(srcaddr);char buf[1024];//3.接收数据recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr*)&srcaddr,&addrlen);printf("--------------------\n");printf("IP   = %s\n",inet_ntoa(srcaddr.sin_addr));printf("post = %d\n",ntohs(srcaddr.sin_port));printf("buf = %s\n",buf);printf("--------------------\n");pid_t pid = fork();if (pid < 0){perror("fork fail");return -1;}if (pid > 0){signal(SIGCHLD,father_handler);c_fd = fd;while (1){//3.接收数据recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr*)&srcaddr,&addrlen);printf("--------------------\n");printf("IP   = %s\n",inet_ntoa(srcaddr.sin_addr));printf("post = %d\n",ntohs(srcaddr.sin_port));printf("buf = %s\n",buf);printf("--------------------\n");if (strncmp(buf,"quit",4) == 0){kill(pid,SIGUSR1);wait(NULL);close(fd);exit(0);}}}else if (pid == 0){signal(SIGUSR1,child_handler);while (1){printf(">");fgets(buf,sizeof(buf),stdin);sendto(fd,buf,strlen(buf) + 1, 0, (const struct sockaddr*)&srcaddr,sizeof(srcaddr));if (strncmp(buf,"quit",4) == 0){close(fd);exit(0);}}}	return 0;
}

基于TCP c/s通信模型

tcp 客户端:

(1)建立连接:

  • socket //买了一部手机;
  • bind //可选   //插上sim卡;
  • connect    //拨打电话 ....

(2)通信过程:(read;write;close) 

connect函数:

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

        (1)功能:该函数固定有客户端使用,表示从当前主机向目标主机发起链接请求。
        (2)参数:sockfd:本地socket创建的套接子id;addr:程目标主机的地址信息;

                        addrlen: 参数2的长度。

        (3)返回值:成功 0;失败 -1;

int main(int argc, const char *argv[])
{int fd = socket(AF_INET,SOCK_STREAM,0);if (fd < 0)handle_error("socket fail");	struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = inet_addr("192.168.1.135");if (connect(fd,(const struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)handle_error("connect fail");return 0;
}

tcp服务器:

(1)建立连接 

  • socket  //买了一部手机 
  • bind    //插上sim卡 
  • listen  //监听 客户端的连接请求 
  • accept  //接听 ---这一步完成之后 连接就建立好了,之后就可以收发数据  

(2)通信过程 (read;write;close) 
     

listen函数:

 int listen(int sockfd, int backlog);

accept函数:

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

int main(int argc, const char *argv[])
{int listen_fd = socket(AF_INET,SOCK_STREAM,0);if (listen_fd < 0)handle_error("socket fail");	struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = inet_addr("192.168.1.135");if (bind(listen_fd,(const struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)handle_error("bind fail");if (listen(listen_fd,5) < 0)handle_error("listen fail");int connfd = accept(listen_fd,NULL,NULL);if (connfd < 0)handle_error("accept fail");printf("connfd = %d\n",connfd);return 0;
}

struct sockaddr *addr //通用地址结构类型,并没有实际去用,实际用到都是具体地址结构类型
           
           struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */
               in_port_t      sin_port;   /* port in network byte order */
               struct in_addr sin_addr;   /* internet address */
           };

           /* Internet address. */
           struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };
     

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com