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 实例- 阻塞的更多相关文章

  1. java tcp socket实例

    java tcp socket实例 2011-04-20 13:58 2364人阅读 评论(1) 收藏 举报 socketjavatcpthreadserverclass package com.ne ...

  2. linux 客户端 Socket 非阻塞connect编程

    开发测试环境:虚拟机CentOS,windows网络调试助手        非阻塞模式有3种用途        1.三次握手同时做其他的处理.connect要花一个往返时间完成,从几毫秒的局域网到几百 ...

  3. Tcp Socket非阻塞recv

    最近看了许多关于网络编程的资料,自己小记一下,以方便以后查找. 什么是阻塞socket,什么是非阻塞socket.对于这个问题,我们要先弄清什么是阻塞/非阻塞.阻塞与非阻塞是对一个文件描述符指定的文件 ...

  4. linux下socket connect 阻塞方式 阻塞时间控制

    同事今天问我,如何在linux下的c代码里面控制connect的阻塞时间.应用的背景是:linux下的c程序有两个目标IP需要connect,如果用阻塞方式,当其中一个IP不能连接的情况下,程序将阻塞 ...

  5. linux下socket编程实例

    linux下socket编程实例一.基本socket函数Linux系统是通过提供套接字(socket)来进行网络编程的.网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符.s ...

  6. Linux C Socket编程原理及简单实例

    部分转自:http://goodcandle.cnblogs.com/archive/2005/12/10/294652.aspx 1.   什么是TCP/IP.UDP? 2.   Socket在哪里 ...

  7. 从linux源码看socket的阻塞和非阻塞

    从linux源码看socket的阻塞和非阻塞 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情. 大部分高性能网络框架采用的是非阻塞模式.笔者这次就从linux ...

  8. Linux 下socket通信终极指南(附TCP、UDP完整代码)

    linux下用socket通信,有TCP.UDP两种协议,网上的很多教程把两个混在了一起,或者只讲其中一种.现在我把自己这两天研究的成果汇总下来,写了一个完整的,适合初学者参考,也方便自己以后查阅. ...

  9. linux一切皆文件之tcp socket描述符(三)

    一.知识准备 1.在linux中,一切皆为文件,所有不同种类的类型都被抽象成文件(比如:块设备,socket套接字,pipe队列) 2.操作这些不同的类型就像操作文件一样,比如增删改查等 二.环境准备 ...

  10. linux socket设置阻塞与非阻塞

    非阻塞IO 和阻塞IO: 在网络编程中对于一个网络句柄会遇到阻塞IO 和非阻塞IO 的概念, 这里对于这两种socket 先做一下说明:       基本概念: 阻塞IO:: socket 的阻塞模式 ...

随机推荐

  1. task host window阻止关机

    在该方法中遇到的问题: 我的电脑是惠普暗影精灵5air,64位的,按照该操作没有效果.这一步中新建的dword默认是32位的,改成新建qword就没有问题了,个人猜测是由于位数不合适的原因造成的. 还 ...

  2. linux部署带ssl的nginx

    1.前期准备 1.1:下载nginx-1.18.0版本  http://nginx.org/download/nginx-1.18.0.tar.gz 然后上传到服      务器 /usr/local ...

  3. vl_nnconv.mexw64找不到指定模块

    在Installing and compiling the library--matconvnet-1.0-beta25时遇到的错误,总是提示"Invalid MEX-file 'C:\Us ...

  4. Ingress限流

    先说结论: ingress节点数量=n0 ingress限流配置 nginx.ingress.kubernetes.io/limit-rps: "n1"   nginx.ingre ...

  5. P1982 [NOIP2013 普及组] 小朋友的数字 题解

    目录 简单版 题目 code 本题 code 简单版 先要会做这道题 题目 P1115 最大子段和https://www.luogu.com.cn/problem/P1115 这道题其实是动态规划,d ...

  6. kubernetes中 flannel网络组件

    Flannel 软件包地址:https://github.com/coreos/flannel Flannel是CoreOS开源的CNI网络插件,下图flannel官网提供的一个数据包经过封包.传输以 ...

  7. 通过python程序让MySQL利用binlog恢复误操作数据

    MySQL利用binlog恢复误操作数据 在人工手动进行一些数据库写操作的时候(比方说数据订正),尤其是一些不可控的批量更新或删除,通常都建议备份后操作.不过不怕万一,就怕一万,有备无患总是好的.在线 ...

  8. ftp服务无法覆盖同名文件

    1.linux修改/etc/pure-ftpd/pure-ftpd.conf的AutoRename  yes 重启ftp服务 2.windows server修改 选中ftp站点,选择右侧高级设置,选 ...

  9. 我眼中的Serverless

    https://cloud.tencent.com/document/product/583 摆脱服务器.存储等底层设备,只上传代码,由云服务器提供服务的触发,维护,调用.

  10. CCPC2021网络赛 1012 Remove

    2021CCPC网络赛 1012 Remove 题意 给定 \(n, m\),然后再给 \(m\) 个素数,问对于所有 \(i \in [1,n]\),将 \(i\) 操作至 \(0\) 的最小操作数 ...