[C++] Linux TCP Socket 实例- 阻塞
Linux平台 TCP Socket通信实例,发现用代码注释记笔记也不错
TCP server 阻塞
1 // 两个进程通过socket进行通信,client需要知道server的,server却不需要实现知道client的。
2 // socket需要知道type和address domain;
3 // address domain:unix domain用于同主机进程间,通过文件系统实现;Internet domain用于两台机器间,需要IP和Port信息。一般2000以下的port保留。
4 // socket type:stream(意味着持续读取,TCP是一种协议)、datagram(一次需要读完整个信息,UDP是一种协议)。
5
6 // port复用机制的理解
7
8 /**
9 stream server
10 1.socket
11 2.bind
12 3.listen
13 4.accept
14 */
15 #include <cstdlib> /* exit() */
16 #include <cstdio> /* perror(): 打印信息+发生错误的原因,可用于定位。 */
17 #include <cstring> /* memset memcpy*/
18 #include <iostream> /* cin cout */
19 #include <sys/types.h> /* 为了满足一些 BSD系统添加头文件*/
20 #include <sys/socket.h> /* socket(); listen(); baccept(); socklen_t */
21 #include <netinet/in.h> /* struct sockaddr_in: 保存socket信息; ntohl(), ntohs(), htonl() and htons()*/
22 #include <unistd.h> /* read() write(), 不是C语言范畴,所以没有cxxxx的实现 */
23 // http://man7.org/linux/man-pages/man2/read.2.html
24 // http://man7.org/linux/man-pages/man2/write.2.html
25
26 /**
27 \brief 错误处理函数
28 */
29 void tzError(const char *msg)
30 {
31 perror(msg);
32 exit(1); // 一般不同原因不同的exit code更为规范
33 }
34
35 /**
36 \brief 主函数
37 */
38 int main(int argc, char *argv[]){
39 // 参数check
40 if (argc < 2) {
41 fprintf(stderr,"ERROR, no [port] arg provided\n");
42 exit(1);
43 }
44 // 生成socke + check
45 int sockfd;
46 sockfd = socket(AF_INET, SOCK_STREAM, 0);
47 // int socket(int domain, int type, int protocol);
48 // http://man7.org/linux/man-pages/man2/socket.2.html
49 // domain:
50 // AF_UNIX 用于本地通信
51 // AF_INET IPv4
52 // AF_INET6 IPv6
53 // type:
54 // SOCK_STREAM 面向连接通信
55 // SOCK_DGRAM 面向无连接通信
56 // protocol:
57 // SOCK_NONBLOCK 非阻塞
58 // SOCK_CLOEXEC 子类不继承父类的socket fd
59 // Return:
60 // 建立的socket:对于server用于监听,对于client用于向指定位置发送
61 if (sockfd < 0){
62 tzError("socket()");
63 }
64 // bind socket + check
65 int port_no = atoi(argv[1]);
66 struct sockaddr_in serv_addr;
67 serv_addr.sin_family = AF_INET; // IPv4
68 serv_addr.sin_addr.s_addr = INADDR_ANY; // 相当于inet_addr("0.0.0.0"),所有网卡。
69 serv_addr.sin_port = htons(port_no); // 需要网络序转换
70 int bind_ret = bind(sockfd,
71 (struct sockaddr*)&serv_addr,
72 sizeof(serv_addr));
73 // int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
74 // http://man7.org/linux/man-pages/man2/bind.2.html
75 // socket()产生sockdf,有了name space(address family)但是没有具体地址,bind完成此任务
76 if( bind_ret<0 ){
77 tzError("bind()");
78 }
79 // listen
80 listen(sockfd,5);
81 // int listen(int sockfd, int backlog);
82 // http://man7.org/linux/man-pages/man2/listen.2.html
83 // listen让sockfd对应的socket成为被动socket,用于accetp
84 // backlog: 最大可以入队等待处理的连接数量。如果大于128(somaxconn)可能被内核截断,cat /proc/sys/net/core/somaxconn
85 // 如果尝试connect的链接超过backlog,client收到ECONNREFUSED错误,如果有重传机制可能忽略此错误。
86 // accept + check
87 struct sockaddr_in client_addr;
88 socklen_t clilen_len = sizeof(client_addr);
89 int new_sockfd = accept(sockfd,
90 (struct sockaddr *) &client_addr,
91 &clilen_len);
92 // int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
93 // http://man7.org/linux/man-pages/man2/accept.2.html
94 // 用于面向连接socket(SOCK_STREAM, SOCK_SEQPACKET),提取队列中第一个请求,创建新的connected socket
95 // 返回新创建的socket的fd,原始的被动sockfd不受影响。
96 // addr: socketaddr指针,记录peer的信息,信息格式取决于socket的定义。
97 // 如果等待队列为空,且socket没有设置nonblocking-->阻塞等待;
98 // 如果等待队列为空,且socket设置nonblocking,返回错误:EAGAIN or EWOULDBLOCK
99
100 // 为了处理对socket的新的connect,可使用:select(2), poll(2), or epoll(7)-->有尝试连接的请求会出触发"readable event"
101 // 也可以通过socket()设置发送SIGIO中断。
102 // addrlen:传入传输参数,实际的大小会重新保存到addrlen中
103 if (new_sockfd < 0)
104 tzError("accept()");
105 // 接收-发送信息
106 #define RECV_BUF_SIZE 256
107 char buffer[RECV_BUF_SIZE];
108 std::memset(buffer, 0, RECV_BUF_SIZE); // 用0进行set
109 int valread = read( new_sockfd , buffer, RECV_BUF_SIZE);
110 std::cout << "read:" << valread << "char, content: " << buffer << std::endl;
111 write(new_sockfd , "get msg", 7);
112 // close sockets
113 close(new_sockfd);
114 close(sockfd);
115
116 return 0;
117 }
118
119 // ref:
120 // https://www.cnblogs.com/fuchongjundream/p/3914696.html
121 // http://www.linuxhowtos.org/C_C++/socket.htm
122 //
TCP Client - 单次连接发送接收测试
1 // 两个进程通过socket进行通信,client需要知道server的,server却不需要实现知道client的。
2 // socket需要知道type和address domain;
3 // address domain:unix domain用于同主机进程间,通过文件系统实现;Internet domain用于两台机器间,需要IP和Port信息。一般2000以下的port保留。
4 // socket type:stream(意味着持续读取,TCP是一种协议)、datagram(一次需要读完整个信息,UDP是一种协议)。
5
6 // port复用机制的理解
7
8 /**
9 stream client
10 1.socket
11 2.connect
12 */
13 #include <cstdlib> /* exit() */
14 #include <cstdio> /* perror(): 打印信息+发生错误的原因,可用于定位。 */
15 #include <cstring> /* memset memcpy strcpy string.c_str()*/
16 #include <iostream> /* cin cout */
17 #include <sys/types.h> /* 为了满足一些 BSD系统添加头文件*/
18 #include <sys/socket.h> /* socket(); listen(); baccept(); socklen_t */
19 // #include <netinet/in.h> /* struct sockaddr_in: 保存socket信息; ntohl(), ntohs(), htonl() and htons()*/
20 #include <netdb.h> /* hostent,IP地址 */
21
22 #include <unistd.h> /* read() write(), 不是C语言范畴,所以没有cxxxx的实现 */
23 // http://man7.org/linux/man-pages/man2/read.2.html
24 // http://man7.org/linux/man-pages/man2/write.2.html
25
26 /**
27 \brief 错误处理函数
28 */
29 void tzError(const char *msg)
30 {
31 perror(msg);
32 exit(1); // 一般不同原因不同的exit code更为规范
33 }
34
35 /**
36 \brief 主函数
37 */
38 int main(int argc, char *argv[]){
39 // 参数check
40 if (argc < 3) {
41 tzError("ERROR, no [IP] [port] arg provided");
42 }
43 // 生成socke + check
44 int sockfd;
45 sockfd = socket(AF_INET, SOCK_STREAM, 0);
46 // int socket(int domain, int type, int protocol);
47 // http://man7.org/linux/man-pages/man2/socket.2.html
48 // domain:
49 // AF_UNIX 用于本地通信
50 // AF_INET IPv4
51 // AF_INET6 IPv6
52 // type:
53 // SOCK_STREAM 面向连接通信
54 // SOCK_DGRAM 面向无连接通信
55 // protocol:
56 // SOCK_NONBLOCK 非阻塞
57 // SOCK_CLOEXEC 子类不继承父类的socket fd
58 // Return:
59 // 建立的socket:对于server用于监听,对于client用于向指定位置发送
60 if (sockfd < 0){
61 tzError("socket()");
62 }
63 // connect + check
64 struct hostent *server;
65 // struct hostent {
66 // char *h_name; /* official name of host */
67 // char **h_aliases; /* alias list */
68 // int h_addrtype; /* host address type */
69 // int h_length; /* length of address */
70 // char **h_addr_list; /* list of addresses */
71 // }
72 // #define h_addr h_addr_list[0] /* for backward compatibility,第一个地址 */
73 server = gethostbyname(argv[1]);
74 if (server == NULL) {
75 tzError("[IP] error");
76 }
77 int port_no = atoi(argv[2]);
78 struct sockaddr_in serv_addr;
79 memset(&serv_addr, 0, sizeof(serv_addr));
80 serv_addr.sin_family = AF_INET; // set type
81 memcpy((char *)server->h_addr, // set addr
82 (char *)&serv_addr.sin_addr.s_addr,
83 server->h_length);
84 serv_addr.sin_port = htons(port_no); // set port
85 int conntect_ret = connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr));
86 if(conntect_ret<0){
87 tzError("connect()");
88 }
89
90 // write and read
91 std::cout << "msg>";
92 std::string msg;
93 std::cin >> msg;
94 #define BUF_SIEE 128
95 char buf[BUF_SIEE];
96 memset(buf, 0, BUF_SIEE);
97 strcpy(buf, msg.c_str());
98 int write_n = write(sockfd, buf, msg.size());
99 std::cout << write_n << " chars send." << std::endl;
100 memset(buf, 0, BUF_SIEE); // 用于输出,依赖\0
101 int read_n = read(sockfd, buf, BUF_SIEE);
102 std::cout << buf << std::endl;
103 std::cout << read_n << " chars read." << std::endl;
104
105 // close sockets
106 close(sockfd);
107
108 return 0;
109 }
110
111 // ref:
112 // http://www.linuxhowtos.org/C_C++/socket.htm
113
[C++] Linux TCP Socket 实例- 阻塞的更多相关文章
- java tcp socket实例
java tcp socket实例 2011-04-20 13:58 2364人阅读 评论(1) 收藏 举报 socketjavatcpthreadserverclass package com.ne ...
- linux 客户端 Socket 非阻塞connect编程
开发测试环境:虚拟机CentOS,windows网络调试助手 非阻塞模式有3种用途 1.三次握手同时做其他的处理.connect要花一个往返时间完成,从几毫秒的局域网到几百 ...
- Tcp Socket非阻塞recv
最近看了许多关于网络编程的资料,自己小记一下,以方便以后查找. 什么是阻塞socket,什么是非阻塞socket.对于这个问题,我们要先弄清什么是阻塞/非阻塞.阻塞与非阻塞是对一个文件描述符指定的文件 ...
- linux下socket connect 阻塞方式 阻塞时间控制
同事今天问我,如何在linux下的c代码里面控制connect的阻塞时间.应用的背景是:linux下的c程序有两个目标IP需要connect,如果用阻塞方式,当其中一个IP不能连接的情况下,程序将阻塞 ...
- linux下socket编程实例
linux下socket编程实例一.基本socket函数Linux系统是通过提供套接字(socket)来进行网络编程的.网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符.s ...
- Linux C Socket编程原理及简单实例
部分转自:http://goodcandle.cnblogs.com/archive/2005/12/10/294652.aspx 1. 什么是TCP/IP.UDP? 2. Socket在哪里 ...
- 从linux源码看socket的阻塞和非阻塞
从linux源码看socket的阻塞和非阻塞 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情. 大部分高性能网络框架采用的是非阻塞模式.笔者这次就从linux ...
- Linux 下socket通信终极指南(附TCP、UDP完整代码)
linux下用socket通信,有TCP.UDP两种协议,网上的很多教程把两个混在了一起,或者只讲其中一种.现在我把自己这两天研究的成果汇总下来,写了一个完整的,适合初学者参考,也方便自己以后查阅. ...
- linux一切皆文件之tcp socket描述符(三)
一.知识准备 1.在linux中,一切皆为文件,所有不同种类的类型都被抽象成文件(比如:块设备,socket套接字,pipe队列) 2.操作这些不同的类型就像操作文件一样,比如增删改查等 二.环境准备 ...
- linux socket设置阻塞与非阻塞
非阻塞IO 和阻塞IO: 在网络编程中对于一个网络句柄会遇到阻塞IO 和非阻塞IO 的概念, 这里对于这两种socket 先做一下说明: 基本概念: 阻塞IO:: socket 的阻塞模式 ...
随机推荐
- iptables(一)基础概念、filter表常用语法规则
iptables简介 netfilter/iptables(简称为iptables)组成Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火 ...
- 论文笔记:Symbolic Execution for Software Testing: Three Decades Later
论文笔记:Symbolic Execution for Software Testing: Three Decades Later 作者 Cristian Cadar 是英国帝国理工学院SRG(Sof ...
- [NOIP1999 提高组] 旅行家的预算
洛咕 题意:一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的).给定两个城市之间的距离 \(D_1\).汽车油箱的容量 \(C\)(以升为单位).每升汽油能行驶的距离 \( ...
- 使用phpexcel导出excel和phpword导出word--简单使用
<?php namespace app\index\controller; //离线环境不能使用composer安装,只能下载包文件,然后放在vendor下,代码中require使用 requi ...
- windows上Yii2使用workerman整套流程
1.在根目录下新建Worker目录 进入新建的Worker文件夹 运行 LINUX下运行 composer require workerman/workerman win 下运行 composer r ...
- 配置中包含maven属性,在idea中本地启动无法正常获取配置
1. 本地启动一个spring cloud 项目,无法启动 (注:测试环境正常),且控台无错误日志. 分析:debug 代码发现是配置无法获取. 查看配置获取方式 是 spring config 通过 ...
- 86、linux离线安装nginx
参考 nginx 离线安装https://blog.csdn.net/ywd1992/article/details/83095855
- 无法加载文件 D:\lunwen\nodejs\node_global\vue.ps1,因为在此系统上禁止运行脚本。visual code页面vue ui启动失败
报如下错误 解决方法: 1.以管理员身份运行 Windows PowerShell(管理员)点击win键 搜索powershell 点击以管理员身份运行 如下图所示 2.输入 set-Executio ...
- Oracle查看异常未提交事务
1.查看归档日志都有哪些 SELECT * from v$archived_log 2.查看某个SCN号的归档文件是否存在 SELECT * from v$archived_log WHERE 113 ...
- 我眼中的Serverless
https://cloud.tencent.com/document/product/583 摆脱服务器.存储等底层设备,只上传代码,由云服务器提供服务的触发,维护,调用.