Linux网络编程--tcp服务器
一、做为 TCP 服务器需要具备的条件呢?
1.具备一个可以确知的地址( bind() ):相当于我们要明确知道移动客服的号码,才能给他们电话;
2.让操作系统知道是一个服务器,而不是客户端( listen() ):相当于移动的客服,他们主要的职责是被动接听用户电话,而不是主动打电话骚扰用户;
3.等待连接的到来( accept() ):移动客服时刻等待着,来一个客户接听一个。
接收端使用 bind() 函数,来完成地址结构与socket 套接字的绑定,这样 ip、port 就固定了,发送端即可发送数据给有明确地址( ip+port ) 的接收端。
对于 TCP 服务器编程流程,有点类似于接电话过程:
1.找个可以通话的手机(socket() )
2.插上电话卡固定一个号码( bind() )
3.职责为被动接听,给手机设置一个铃声来监听是否有来电( listen())
4. 有来电,确定双方的关系后,才真正接通不挂电话( accept() )
5. 接听对方的诉说( recv() )
6.适当给些回话( send() )
7.通信结束后,双方说再见挂电话( close())。
int bind( int sockfd, const struct sockaddr *myaddr,socklen_t addrlen );
功能:
将本地协议地址与 sockfd 绑定,这样 ip、port 就固定了
参数:
sockfd:socket 套接字myaddr: 指向特定协议的地址结构指针
addrlen:该地址结构的长度
返回值:
成功:返回 0
失败:-1
注意:bind只能绑定自身的地址及端口
使用实例:
[csharp] view plaincopy
- // 设置本地地址结构体
- struct sockaddr_in my_addr;
- bzero(&my_addr, sizeof(my_addr)); // 清空,保证最后8字节为0
- my_addr.sin_family = AF_INET; // ipv4
- my_addr.sin_port = htons(port); // 端口
- my_addr.sin_addr.s_addr = htonl(INADDR_ANY);// ip,INADDR_ANY为通配地址其值为0
- // 绑定
- int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
- if( err_log != 0)
- {
- perror("binding");
- close(sockfd);
- exit(-1);
- }
int listen(int sockfd, int backlog);
功能:
将套接字由主动修改为被动,使操作系统为该套接字设置一个连接队列,用来记录所有连接到该套接字的连接。更详细说明,请看《connect()、listen()和accept()三者的关系》。
参数:
sockfd: socket监听套接字
backlog:连接队列的长度
返回值:
成功:返回0
失败:其他
int accept( int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen );
功能:
从已连接队列中取出一个已经建立的连接,如果没有任何连接可用,则进入睡眠等待(阻塞)。更详细说明,请看《connect()、listen()和accept()三者的关系》。
参数:
sockfd: socket监听套接字
cliaddr: 用于存放客户端套接字地址结构
addrlen:套接字地址结构体长度的地址
返回值:
成功:已连接套接字。注意:返回的是一个已连接套接字,这个套接字代表当前这个连接
失败:< 0
tcp_server代码:
[csharp] view plaincopy
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- int main(int argc, char *argv[])
- {
- unsigned short port = 8000; // 本地端口
- if(argc > 1)
- {
- port = atoi(argv[1]);
- }
- //1.创建通信端点:套接字
- int sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if(sockfd < 0)
- {
- perror("socket");
- exit(-1);
- }
- //设置本地地址结构体
- struct sockaddr_in my_addr;
- bzero(&my_addr, sizeof(my_addr)); // 清空,保证最后8字节为0
- my_addr.sin_family = AF_INET; // ipv4
- my_addr.sin_port = htons(port); // 端口
- my_addr.sin_addr.s_addr = htonl(INADDR_ANY);// ip,INADDR_ANY为通配地址其值为0
- //2.绑定:将本地ip、端口与套接字socket相关联起来
- int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
- if( err_log != 0)
- {
- perror("binding");
- close(sockfd);
- exit(-1);
- }
- //3.监听,监听套接字改为被动,创建连接队列
- err_log = listen(sockfd, 10);
- if(err_log != 0)
- {
- perror("listen");
- close(sockfd);
- exit(-1);
- }
- printf("listen client @port=%d...\n",port);
- while(1)
- {
- struct sockaddr_in client_addr;
- char cli_ip[INET_ADDRSTRLEN] = "";
- socklen_t cliaddr_len = sizeof(client_addr);
- int connfd = 0;
- //4.从完成连接队列中提取客户端连接
- connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);
- if(connfd < 0)
- {
- perror("accept");
- continue;
- }
- inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);
- printf("----------------------------------------------\n");
- printf("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port));
- char recv_buf[512] = "";
- while( recv(connfd, recv_buf, sizeof(recv_buf), 0) > 0 ) // 接收数据
- {
- printf("\nrecv data:\n");
- printf("%s\n",recv_buf);
- }
- close(connfd); //关闭已连接套接字
- printf("client closed!\n");
- }
- close(sockfd); //关闭监听套接字
- return 0;
- }
用windows的网络调试助手作为客户端,上面代码为服务器
运行结果:关闭连接:close()
使用 close() 函数即可关闭套接字,关闭一个代表已连接套接字将导致另一端接收到一个 0 长度的数据包,详情请看《 TCP 四次挥手》。
做服务器时
- 关闭监听套接字( socket()和listen()之后的套接字 )将导致服务器无法接收新的连接,但不会影响已经建立的连接;
- 关闭 accept()返回的已连接套接字将导致它所代表的连接被关闭,但不会影响服务器的监听( socket()和listen()之后的套接字 )。
做客户端时
关闭连接就是关闭连接,不意味着其他。
如果客户端和服务器已经连接成功的前提下,通常的情况下,先关闭客户端,再关闭服务器,如果是先关闭服务器,立马启动服务器是,服务器绑定的端口不会立马释放(如下图),要过 1 分钟左右才会释放,为什么会这样的呢?请看《 TCP 四次挥手》。有没有方法让服务器每次启动都能立即成功?请看《端口复用》。
源码下载:
Linux网络编程--tcp服务器相关推荐
- Linux 网络编程 TCP
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍 客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客 ...
- Linux网络编程——tcp并发服务器(poll实现)
https://blog.csdn.net/lianghe_work/article/details/46535859 想详细彻底地了解poll或看懂下面的代码请参考<Linux网络编程--I/ ...
- Linux网络编程——tcp并发服务器(多进程)
https://blog.csdn.net/lianghe_work/article/details/46503895 一.tcp并发服务器概述 一个好的服务器,一般都是并发服务器(同一时刻可以响应多 ...
- Linux 网络编程——TCP编程
概述 TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议. TCP 具有以下特点: 1)电话系统服务模式的抽象 2) ...
- linux网络编程tcp和udp基本函数调用过程及如何选择
1. socket编程 1.1 概述 TCP是TCP/IP体系中面向连接的传输层协议,它提供全双工和可靠交付的服务.它采用许多机制来确保端到端结点之间的可靠数据传输,如采用序列号.确认重传.滑动窗口等 ...
- QT网络编程——TCP服务器和客户端通信
目录 一.服务器端 1.QT中TCP服务器的开发思路 2.QT服务器界面设计 3.QT服务器代码实现 二.客户端 1.QT中TCP客户端的开发思路 2.QT客户端界面设计 3.QT客户端代码实现 网络 ...
- Linux 网络编程——并发服务器的三种实现模型
服务器设计技术有很多,按使用的协议来分有 TCP 服务器和 UDP 服务器,按处理方式来分有循环服务器和并发服务器. 循环服务器与并发服务器模型 在网络程序里面,一般来说都是许多客户对应一个服务器(多 ...
- Linux网络编程——tcp并发服务器(epoll实现)
https://blog.csdn.net/lianghe_work/article/details/46551871 通过epoll实现tcp并发回执服务器(客户端给服务器发啥,服务器就给客户端回啥 ...
- Linux网络编程——tcp并发服务器(I/O复用之select)
https://blog.csdn.net/lianghe_work/article/details/46519633 与多线程.多进程相比,I/O复用最大的优势是系统开销小,系统不需要建立新的进程或 ...
- Linux网络编程——tcp并发服务器(多线程)
https://blog.csdn.net/lianghe_work/article/details/46504243 tcp多线程并发服务器 多线程服务器是对多进程服务器的改进,由于多进程服务器在创 ...
最新文章
- python 把列表或者元组转成集合
- 发票管理软件_企业为什么需要ERP企业管理软件?
- oracle数据库常用的语法与复合函数
- 请编写一个程序,用于统计字符串中每个字母的出现次数(字母忽略大小写),统计出结果后,请按照{'a':3,'b':2}的格式输出。
- 华为交换机关闭Telnet、开启SSH服务命令
- 基于JAVA+Spring+MYSQL的电影票预定系统
- UIDatePicker的属性与方法
- javamail发送邮件,解决被垃圾邮件问题
- java新手笔记6 示例for
- win10应用商店无法安装
- 路畅安卓最新固件升级_路畅导航系统固件升级大全下载 v1.51 官方版
- 010Editor相关
- 维基百科中文语料建模
- 简单的动画(梦幻西游)
- css制作三角形、带三角文本框、价格三角框
- linux bsd格式,Linux系统日志管理_Linux/BSD系统
- 华硕服务器不分区重装系统,华硕笔记本重装系统不能进入系统怎么办
- Vue.use 写多个_老师说“你女儿跟多个男生早恋”,爸爸的回应改变了女儿的一生|早恋|马伊琍|晓敏|老师|告白...
- web前端之幻灯片(二)--自动播放
- sql2005java驱动_Microsoft SQL Server 2005 JDBC驱动程序