建立TCP连接,实现基本通信
来源:互联网 发布:淘宝香帝缘 编辑:程序博客网 时间:2024/05/01 21:55
1、TCP连接服务器端需要做的事情描述:
建立监听套接字(socket函数),绑定监听接口(bind函数),进行监听(listen),调用connect函数等待在监听套接字上等待连接套接字的描述符:
1. 创建监听套接字,并绑定监听接口:
int sockfd = socket(AF_INET,SOCK_STREAM,0); // AF_INET说明为 IPV4协议,SOCK_STREAM说明为套接字流 sockaddr_in servaddr; //ipv4支持的地址格式为 sockaddr_in,网络传输支持的地址格式为 sockaddr //初始化监听套接字要绑定的地址,其中输入地址绑定为 INADDR_ANY bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); //监听端口号为 PORT servaddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sockfd,(sockaddr*)&servaddr,sizeof(servaddr));
2.进行监听并返回连接的套接字
int connfd; listen(sockfd,LISTENQ); //LISTENQ为允许的最大的监听排队套接字,自定义 for(;;) { connfd = accept(sockfd,NULL,NULL); //获得连接的套接字描述符,可以通过该描述符进行通信 }
定义 Tcp_serv()函数,返回一个已建立好并保持监听的套接字
int Tcp_serv(){ int sockfd = socket(AF_INET,SOCK_STREAM,0); sockaddr_in servaddr; bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(9999); //监听端口号为 9999 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sockfd,(sockaddr*)&servaddr,sizeof(servaddr)); listen(sockfd,8); return sockfd;}
2、TCP连接客户端做的事情:
建立套接字,设定服务器端的地址,调用connect将套接字连接到服务器
int sockfd = socket(AF_INET,SOCK_STREAM,0); int n; sockaddr_in servaddr; bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); //与服务器端绑定的端口号相同的端口号 inet_pton(AF_INET,ADDR,&servaddr.sin_addr); //ADDR为服务器的IP地址,需要自定义 //重复建立连接,最多尝试10次,直到连接成功建立 //*****需要特别注意,当connect失败想要重连时,需要使用新的socket套接字描述符 for(; n != 10; ++n) { sockfd = socket(AF_INET,SOCK_STREAM,0); if(connect(sockfd,(sockaddr *)&servaddr,sizeof(servaddr)) >=0 ) break; //connect失败,准备重连 cout << n << "times connect failed" << endl; close(sockfd); } if(n == 10) cout << “connect error” << endl; //连接成功建立,使用套接字描述符 sockfd 与服务器端进行通信
定义 Tcp_cli()函数,返回一个已建立好并保持监听的套接字
int Tcp_cli(){ int sockfd = socket(AF_INET,SOCK_STREAM,0); int n; sockaddr_in servaddr; bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(9999); inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr); //以环回地址为例 for(; n != 10; ++n) { sockfd = socket(AF_INET,SOCK_STREAM,0); if(connect(sockfd,(sockaddr *)&servaddr,sizeof(servaddr)) >=0 ) break; //connect失败,准备重连 cout << n << "times connect failed" << endl; close(sockfd); } if(n == 10) cout << “connect error” << endl; return sockfd;}
3、基于网络套接字的读取函数,实现每次读取返回一行,包含换行符:
//从套接字描述符sockfd中读取一行,并放入string参数中int Read(int sockfd,string & str) { char * head = NULL; size_t n = 0; //将套接字描述符当做文件描述符来使用,打开其文件流,使用 getline()函数 FILE * input = fdopen(sockfd,"r"); //getline()函数从文件流中读取一行信息放入 head 地址空间中,若 head == NULL,则自动分配足够空间,返回读取的数据大小,***注:包含换行符,出错返回 <= 0 num = getline(&head,&n,inout); if(num < 0) return -1; str = string(head); free(head); //释放空间 return num;}
4、基于网络套接字的写函数:
//将 string 参数中的字符全写到套接字 sockfd 中size_t Write(int sockfd,const string & str){ char buf[BUFSIZE]; //BUFSIZE 为最大传输的串的长度,可自定义。假设: #define BUFSIZE 1024 size_t len = str.size(); ssize_t n; char * ptr = buff; strcpy(buff,str.c_str()); while(len > 0) { if((n = write(sockfd,ptr,len)) <= 0) { if(n < 0 && errno == EINTR) n = 0; else return -1; } len -= n; ptr += n; } return n;}
5、一个例子:
服务器端:
//serv.cppint main(int argc,char ** argv){ int sockfd = Tcp_serv(); pid_t pid; int connfd; for(;;) { connfd = accept(sockfd,NULL,NULL); if((pid = fork()) < 0) { cout << "fork error" << endl; return -1; } else if(pid == 0) { //服务器实现回射功能 close(sockfd); string msg; while(Read(connfd,msg) > 0) Write(connfd,msg); exit(0); } close(connfd); }}
客户端:
//client.cppint main(){ int sockfd = Tcp_cli(); string info; while(Read(STDIN_FILENO,info) > 0) { Write(sockfd,info); Read(sockfd,info); cout << "come from net is : " << info << flush; //包含换行符 }}
0 0
- 建立TCP连接,实现基本通信
- API SOCKET基础(一) TCP建立连接并通信
- API SOCKET基础(一) TCP建立连接并通信
- API SOCKET基础(一) TCP建立连接并通信
- tcp/udp建立连接并通信的过程
- 建立TCP通信
- 建立TCP通信
- TCP建立连接_legend050709
- TCP连接建立、关闭
- TCP协议---建立连接
- CSocket建立TCP连接
- TCP建立,释放连接
- TCP建立连接过程
- TCP连接建立断开
- TCP建立,释放连接
- 【通信】TCP建立连接协议是三次握手,而关闭连接却是四次握手
- 建立tcp/ip连接,vc6实现客户端(发送数据)
- C# 实现基本的套接字TCP通信
- MFC中持久化的实现
- HDU 5056 双指针(也叫窗口滑动(也叫尺取法))
- HDU 5137 How Many Maos Does the Guanxi Worth <迪杰斯特拉算法变形>
- Unity_UNity导出Android工程
- 80元,100元,300元,500元低价出售40个不错的老域名
- 建立TCP连接,实现基本通信
- Accelerated C++ 学习笔记3
- 输出所有对象的属性名,并放入一个数组
- 数据对齐
- 9.11排序与查找(七)——叠罗汉
- spingMVC模块handlerMapping的初始化过程
- 如何完全退出android应用程序
- "App Timeline Server"重启失败解决办法
- (2.1.22)JDBC为什么要使用PreparedStatement而不是Statement