TCP网络编程的基本流程

TCP网络编程的基本流程

对于服务端,通常为以下流程:

  1. 调用socket函数创建socket
  2. 调用bind函数将socket绑定到某个IP和端口上
  3. 调用listen开始监听
  4. 当有客户端请求连接上来时,调用accept函数接受连接,产生一个新的socket
  5. 基于新产生的socket调用sendrecv函数,开始与客户端进行数据交流
  6. 通信结束后,调用close函数关闭套接字

对于客户端,通常为以下流程:

  1. 调用socket函数创建客户端socket

  2. 调用connect函数尝试连接服务器

  3. 连接成功后调用sendrecv函数,开始与服务器进行通信

  4. 通信结束后,调用close函数关闭socket

111

服务端代码实现如下:

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#pragma clang diagnostic push
#pragma ide diagnostic ignored "EndlessLoop"
using std::cout;
using std::endl;
int main(int argc,char * argv[])
{//1.create socketint listenfd = socket(AF_INET,SOCK_STREAM,0);if(listenfd == -1){cout<<"create listenfd failed"<<endl;return -1;}//2.Initialize server addressstruct sockaddr_in bindaddr{};bindaddr.sin_family =AF_INET;bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);bindaddr.sin_port= htons(3000);if (bind(listenfd,(struct  sockaddr*) &bindaddr, sizeof(bindaddr)) == -1){cout<<"bind listen socket failed!"<<endl;return -1;}//3.Start listeningif(listen(listenfd,SOMAXCONN) == -1){cout<<"listen error"<<endl;return -1;}while (true){sockaddr_in clientaddr{};socklen_t  clientaddrlen = sizeof(clientaddr);//4.accept client connectint clientfd = accept(listenfd,(struct sockaddr*)&clientaddr,&clientaddrlen);if (clientfd != -1){//5.Receive data from the clientchar recvBuf[32]={0};int ret = recv(clientfd,recvBuf,32,0);if (ret > 0){cout<<"Receive data from the client:"<<recvBuf<<endl;ret = send(clientfd,recvBuf, strlen(recvBuf),0);if(ret != strlen(recvBuf))cout<<"send failed"<<endl;elsecout<<"send successfully"<<endl;}else{cout<<"Receive data error"<<endl;}close(clientfd);}}//7.close listenclose(listenfd);return 0;
}
#pragma clang diagnostic pop

客户端代码

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>#define SERVER_ADDRESS "127.0.0.1"
#define SERVER_PORT 3000
#define SEND_DATA "helloworld"int main(int argc,char *argv[])
{//1.create socketint clientfd = socket(AF_INET,SOCK_STREAM,0);if(clientfd == -1){std::cout<<"create socket failed"<<std::endl;return -1;}//2.connect serversockaddr_in serveraddr;serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr= inet_addr(SERVER_ADDRESS);serveraddr.sin_port= htons(SERVER_PORT);if (connect(clientfd,(struct sockaddr*) &serveraddr, sizeof(serveraddr)) == -1){std::cout<<"connect socket error"<<std::endl;return -1;}//3. send data to serverint ret= send(clientfd,SEND_DATA, strlen(SEND_DATA),0);if (ret != strlen(SEND_DATA)){std::cout<<"send data failed"<<std::endl;return -1;}std::cout<<"successfully"<<SEND_DATA<<std::endl;//4.recv data from serverchar recvBuf[32] ={0};ret = recv(clientfd,recvBuf,32,0);if(ret >0){std::cout<<"sucessfully"<<std::endl;} else{std::cout<<"failed"<<recvBuf<<std::endl;}//5.close socketclose(clientfd);return 0;
}

TCP网络编程的基本流程

Linux与C++11多线程编程(学习笔记)

Linux select函数用法和原理

socket的阻塞模式和非阻塞模式(send和recv函数在阻塞和非阻塞模式下的表现)

connect函数在阻塞和非阻塞模式下的行为

获取socket对应的接收缓冲区中的可读数据量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/408169.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux select函数用法和原理

select函数的用法和原理 Linux上的select函数 select函数用于检测一组socket中是否有事件就绪.这里的事件为以下三类: 读事件就绪 在socket内核中,接收缓冲区中的字节数大于或者等于低水位标记SO_RCVLOWAT,此时调用rec或read函数可以无阻塞的读取该文件描述符,并且返回值大于…

常见日期方法荟萃

一.如何获得当月有多少天 intmSystem.DateTime.DaysInMonth(System.DateTime.Now.Year,System.DateTime.Now.Month);二.日期型格式处理通用方法1.在webconfig中配置如下<add key"ShortDatePattern"value"MM-dd-yyyy"/><add key"LongDatePatt…

socket的阻塞模式和非阻塞模式(send和recv函数在阻塞和非阻塞模式下的表现)

socket的阻塞模式和非阻塞模式 无论是Windows还是Linux,默认创建socket都是阻塞模式的 在Linux中,可以再创建socket是直接将它设置为非阻塞模式 int socket (int __domain, int __type, int __protocol)将__type增加SOCK_NOBLOCK 不仅如此,在Linux上直接利用accept函数返回…

connect函数在阻塞和非阻塞模式下的行为

connect函数在阻塞和非阻塞模式下的行为 当socket使用阻塞模式时,connect函数会阻塞到有明确结果才会返回,如果网络环境较差,可能要等一会,影响体验, 为了解决这个问题,我们使用异步connect技术 创建socket,将socket设置为非阻塞模式 调用connect函数,此时无论connect函数是…

获取socket对应的接收缓冲区中的可读数据量

获取socket对应的接收缓冲区中的可读数据量 本文介绍如何获取当前socket对应的接收缓冲区的可读数据量 在Linux上可以使用ioctl函数 #include <sys/ioctl.h>int ioctl (int __fd, unsigned long int __request, ...)来看一个例子: #include <sys/types.h> #in…

Linux epoll的用法

Linux epoll的用法 epollfd_create函数 #include <sys/epoll.h>int epoll_create (int __size)参数含义__size此参数从Linux 2.6.8后就不再使用了,但必须设置成大于零的值 返回值含义>0可用的epollfd-1调用失败 epollfd_ctl函数 有了epollfd,我们需要将要检测事件…

windows网络编程

windows网络编程 TCP编程 服务端 这里我们有几点需要注意: 使用WSAStartup初始化网络库,即将与socket函数相关dll文件加载到进程地址空间中退出时,使用WSACleanup()卸载相关dll文件与Linux使用close函数关闭socket不同,windows需要使用closesocket函数关闭socket WSAStart…

TCP服务器epoll的多种实现

TCP服务器epoll的多种实现 对于网络IO会涉及到两个系统对象 用户空间中进程或者线程操作系统内核 比如发生read操作时就会经历两个阶段 等待数据就绪将数据从内核缓冲区拷贝到用户缓冲区 由于各个阶段多有不同的情况,一组合么就产生了多种网络 IO 模型 阻塞IO 在Linux中…