TCP/IP编程——基于TCP的半关闭
在TCP服务端和客户端建立连接之后服务端和客户端会分别有两个独立的输入流和输出流,而且相互对应。服务端的输出流对应于客户端的输入流,服务端的输入流对应于客户端的输出流。这是在建立连接之后的状态。
当我们调用close()函数时,系统会同时把双方的输入流和输出流全部关闭,但是有时候我们仍需要在一方断开连接之后只进行接受数据或者传输数据其中一项操作。这时就需要我们只断开输入或者输出,保留另一个流的正常运转,也就引入了TCP的半关闭状态。
基本操作:
之前我们传输完数据之后便直接调用了close()函数,我们可以使用系统提供的shutdown()函数方便的完成TCP的半关闭。
shutdown(int socket , int type):半关闭套接字中的输入或者输出流
- socket(套接字描述符):需要断开的套接字描述符
- type(断开类型):套接字的断开方式
SHUT_RD——断开输入流,并清空输入缓冲中的数据
SHUT_WR——断开输出流,并将输出缓冲中的数据输出
SHUT_RDWR——同时断开输入输出流,分两次调用shutdown()函数
成功时返回0,失败时返回-1
服务端:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h> #define BUFF_SIZE 30 void error_handling(char *message); /**
基于TCP的半连接服务端
**/
int main(int argc ,char *argv[]){
//客户端和服务端的socket描述符
int serv_sock;
int clent_sock;
//客户端和服务端的地址
struct sockaddr_in serv_addr;
struct sockaddr_in clent_addr;
//客户端地址大小
socklen_t client_addr_size;
//用于记录读取的文件字节数
int read_count;
//缓冲大小
char buff[BUFF_SIZE];
//用于打开文件的文件指针
FILE *fp;
//检查输入的参数个数是否合法
if(argc!=2){
printf("Usage : %s <port> \n ",argv[0]);
exit(1);
} //使用文件描述符打开文件
fp = fopen("word_file.txt","rb");
//创建服务端saocket
serv_sock = socket(AF_INET,SOCK_STREAM,0);
//将server_addr中的内容清空
memset(&serv_addr,0,sizeof(serv_addr));
//初始化socket地址
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(atoi(argv[1])); //进行地址绑定
if(bind(serv_sock,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) == -1){
error_handling("bind() error");
}
//使服务端进入监听状态
if(listen(serv_sock,5) == -1){
error_handling("listen() error");
}
//获的客户端地址的大小
client_addr_size = sizeof(clent_addr);
clent_sock = accept(serv_sock,(struct sockaddr *) &clent_addr,&client_addr_size); while(1){
//读取的文件字节数
read_count = fread((void *) buff,1,BUFF_SIZE,fp);
//向客户端写入数据
if(read_count<BUFF_SIZE){
write(clent_sock,buff,read_count);
break;
}
write(clent_sock,buff,BUFF_SIZE);
}
/**
在数据输出完成之后,对输出流进行流半关闭
这种状态下服务读不能向客户端写入数据,但是可以接受来自客户端的数据
**/
shutdown(clent_sock,SHUT_WR);
//接受来自客户端的消息
while(0 == read(clent_sock,buff,BUFF_SIZE))
{
continue;
}
//打印消息
printf("Message from client : %s \n",buff);
//关闭文件
fclose(fp);
write(clent_sock,"11111",5);
//彻底关闭TCP连接
//close(clent_sock);
//close(serv_sock);
//避免因进程退出,导致 server 向 client 发 FIN
while(1){};
return 0;
} void error_handling(char * message){
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
客户端:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h> #define BUFF_SIZE 30 void error_handling(char *message); int main(int argc ,char *argv[]){
int sock;
FILE *fp; char buff[BUFF_SIZE];
int read_count;
struct sockaddr_in server_addr; if(argc!=3){
printf("Usage : %s <port> \n ",argv[0]);
exit(1);
} fp = fopen("recevice.dat","wb");
sock = socket(AF_INET,SOCK_STREAM,0); memset(&server_addr,0,sizeof(server_addr)); //初始化socket地址
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
server_addr.sin_port = htons(atoi(argv[2])); connect(sock,(struct sockaddr *) &server_addr,sizeof(server_addr)); while(read_count = read(sock,buff,BUFF_SIZE) != 0){
//向文件中写入读取到的数据
printf("recv data from server : %s\n",buff);
fwrite((void *) buff,1,read_count,fp);
}
//打印接收到的数据
puts("Recevied file data");
//接收完成之后向服务端发送一个消息
// 睡3秒,确保server端 shutdown()已执行
sleep(3);
write(sock,"Thank you ",10);
write(sock,"server",6); //关闭文件和socket连接
fclose(fp);
// 避免因进程退出,导致 client 向 server 发 FIN
while(1){};
//close(sock);
return 0;
} void error_handling(char * message){
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
至此就完成了一个基于半关闭的TCP服务端/客户端程序,这样使得服务端在传输完数据之后可以只保留输入流,关闭输出流。
抓包:https://files.cnblogs.com/files/yorkyang/tcp%E5%8D%8A%E5%85%B3%E9%97%AD.zip
转自:http://blog.csdn.net/wqc_csdn/article/details/51543504
TCP/IP编程——基于TCP的半关闭的更多相关文章
- linux tcp/ip编程和windows tcp/ip编程差别以及windows socket编程详解
最近要涉及对接现有应用visual c++开发的tcp客户端,花时间了解了下windows下tcp开发和linux的差别,从开发的角度而言,最大的差别是头文件(早期为了推广尽可能兼容,后面越来越扩展, ...
- 网络编程(二)——TCP协议、基于tcp协议的套接字socket
TCP协议与基于tcp协议的套接字socket 一.TCP协议(流式协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的 ...
- Java 网络编程 -- 基于TCP 模拟多用户登录
Java TCP的基本操作参考前一篇:Java 网络编程 – 基于TCP实现文件上传 实现多用户操作之前先实现以下单用户操作,假设目前有一个用户: 账号:zs 密码:123 服务端: public c ...
- TCP/IP笔记(二)TCP/IP简介
上回,主要介绍了下协议和OSI参考模型,并简单了解下网络构成要素,这回该说说TCP/IP了 互联网与TCP/IP的关系 互联网进行通信时,需要相应的网络协议,TCP/IP原本就是为使用互联网而开发 ...
- TCP/IP 协议图--TCP/IP 基础
1. TCP/IP 的具体含义 从字面意义上讲,有人可能会认为 TCP/IP 是指 TCP 和 IP 两种协议.实际生活当中有时也确实就是指这两种协议.然而在很多情况下,它只是利用 IP 进行通信时所 ...
- tcp/ip学习笔记-TCP
tcp/ip学习笔记-TCP 彭会锋 报文发送采用的是tcp_output函数,
- TCP/IP协议图--TCP/IP基础
1. TCP/IP 的具体含义 从字面意义上讲,有人可能会认为 TCP/IP 是指 TCP 和 IP 两种协议.实际生活当中有时也确实就是指这两种协议.然而在很多情况下,它只是利用 IP 进行通信时所 ...
- OSI参考模型与TCP/IP参考模型与TCP/IP协议栈
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11484126.html OSI参考模型与TCP/IP参考模型与TCP/IP协议栈 TCP/IP分层模型 ...
- 20181225 基于TCP/IP和基于UDP/IP的套接字编程
一.TCP/IP的套接字编程 服务器端代码: import socketserver = socket.socket() # 默认是基于TCP# 基于TCP的对象serve=socket.sock ...
随机推荐
- [LeetCode] 130. Surrounded Regions_Medium tag: DFS/BFS
Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'. A reg ...
- Linux和windows 查看程序、进程的依赖库的方法
Linux: 1. 利用ldd查看可执行程序的依赖库 [root@~]# ldd /usr/local/php/bin/php linux-vdso.so.1 => (0x00007ff ...
- 线程间操作无效: 从不是创建控件“button1”的线程访问它。
.net2后是不能跨线程访问控件的.,窗体上的控件是当前线程创建的,当用户异步执行一个方法:在该方法中给窗体上的控件赋值,记住:当执行一个异步委托的时候,其实 就是开了一个线程去执行那个方法,这样就会 ...
- Eclipse集成Hibernate操作Sqlserver实例
Eclipse搭建Hibernate开发环境,使用的数据库是Sqlserver2008 1.需要成功安装Eclipse,如果没有安装可以上网查资料. 2.Eclipse安装成功后,点击Help--&g ...
- Linux.超级管理员root-密码破解
Linux.超级管理员root-密码破解 环境: 我是在虚拟机中安装的Linux,然后进行破解的.实体机,应该也是可以的,但我没有尝试过.如果你有实体机,试试吧... 又不要钱~ 在系统启动的时候,会 ...
- LeetCode110.平衡二叉树
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1. 示例 1: 给定二叉树 [3,9,20,null,null,15,7] 3 / \ 9 20 / \ 15 7 返回 true . 示例 ...
- javaweb之验证码验证技术
今天学习了一个验证码校验技术,所以就写下了一些笔记,方便日后查看.首先创建web工程 1.然后在src目录下创建一个Servlet类,此类用来显示登录页面和错误信息提示 package com.LHB ...
- 多语言(Java、.NET、Node.js)混合架构下开源调用链追踪APM项目初步选型
1. 背景 我们的技术栈包括了Java..NET.Node.js等,并且采用了分布式的技术架构,系统性能管理.问题排查成本越来越高. 2. 基本诉求 针对我们的情况,这里列出了选型的主要条件,作为最终 ...
- js函数集
js函数集·字符串(String) 1.声明 var myString = new String("Every good boy does fine."); var myStrin ...
- JVM探秘4---垃圾收集器介绍
Java虚拟机有很多垃圾收集器 下面先来了解HotSpot虚拟机中的7种垃圾收集器:Serial.ParNew.Parallel Scavenge.Serial Old.Parallel Old.CM ...