Socket通讯
复习贴,资料大多来自百科.看了一遍理解了一遍,把绕口的话按语义给改了`_>`
对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。
用户开始Socket连接时, 首先申请一个Socket号码;同时要知道对方的号码. 然后向对方发出连接请求(假如对方不在同一局域网相当于给出网络地址). 假如对方在场并空闲(相当于通信的另一主机开机且可以接受连接请求),双方就可以Socket通信, 连接成功。双方建立连接通讯过程,向Socket发送数据和从socket接收数据。通话结束后,一方挂起电话机相当于关闭Socket,撤消连接。
连接过程
绑定
接收
发送
接收连接请求
- /* File Name: server.c */
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #include<errno.h>
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<netinet/in.h>
- #define DEFAULT_PORT 8000 //默认端口
- #define MAXLINE 4096 //最大行数
- int main(int argc, char** argv)
- {
- int socket_fd, connect_fd;
- struct sockaddr_in servaddr;
- char buff[];
- int n;
- //初始化Socket
- if( (socket_fd = socket(AF_INET, SOCK_STREAM, )) == - ) //流式Socket(SOCK_STREAM)是一种面向连接的Socket,针对于面向连接的TCP服务应用。数据报式Socket(SOCK_DGRAM)是一种无连接的Socket,对应于无连接的UDP服务应用。
- {
- printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
- exit();
- }
- //初始化
- memset(&servaddr, , sizeof(servaddr));
- servaddr.sin_family = AF_INET; //AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址。 htonl,host to network, l 的意思是返回类型是long 将主机数转换成无符号长整形的网络字节顺序。
- servaddr.sin_port = htons(DEFAULT_PORT);//设置的端口为DEFAULT_PORT htons将一个无符号短整型的主机数值转换为网络字节顺序,即大尾顺序(big-endian)
- //将本地地址绑定到所创建的套接字上
- if( bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -)
- {
- printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
- exit();
- }
- //开始监听是否有客户端连接
- if( listen(socket_fd, ) == -)
- {
- printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
- exit();
- }
- printf("======waiting for client's request======\n");
- while()
- {
- //阻塞直到有客户端连接,不然多浪费CPU资源。
- if( (connect_fd = accept(socket_fd, (struct sockaddr*)NULL, NULL)) == -)
- {
- printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
- continue;
- }
- //接受客户端传过来的数据
- n = recv(connect_fd, buff, MAXLINE, );
- //向客户端发送回应数据
- if(!fork())
- { /*子进程*/
- if(send(connect_fd, "Hello,you are connected!\n", ,) == -)
- perror("send error");
- close(connect_fd);
- exit();
- }
- buff[n] = '\0';
- printf("recv msg from client: %s\n", buff);
- close(connect_fd);
- }
- close(socket_fd);
- }
- /* File Name: client.c */
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #include<errno.h>
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<netinet/in.h>
- #define MAXLINE 4096
- int main(int argc, char** argv)
- {
- int sockfd, n,rec_len;
- char recvline[], sendline[];
- char buf[MAXLINE];
- struct sockaddr_in servaddr;
- if( argc != )
{- printf("usage: ./client <ipaddress>\n");
- exit();
- }
- if( (sockfd = socket(AF_INET, SOCK_STREAM, )) < )
{- printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
- exit();
- }
- memset(&servaddr, , sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons();
- if( inet_pton(AF_INET, argv[], &servaddr.sin_addr) <= )
{- printf("inet_pton error for %s\n",argv[]);
- exit();
}- if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < )
{- printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
- exit();
- }
- printf("send msg to server: \n");
- fgets(sendline, , stdin);
- if( send(sockfd, sendline, strlen(sendline), ) < )
- {
- printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
- exit();
- }
- if((rec_len = recv(sockfd, buf, MAXLINE,)) == -)
{- perror("recv error");
- exit();
- }
- buf[rec_len] = '\0';
- printf("Received : %s ",buf);
- close(sockfd);
- exit();
- }
- //Server服务端
- #include<winsock2.h>
- #include<stdio.h>
- #pragmacomment(lib,"ws2_32.lib")
- void main()
- {
- WSADATA wsaData;
- SOCKET sockServer;
- SOCKADDR_IN addrServer;
- SOCKET sockClient;
- SOCKADDR_IN addrClient;
- WSAStartup(MAKEWORD(,),&wsaData);
- sockServer=socket(AF_INET,SOCK_STREAM,);
- addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//INADDR_ANY表示任何IP
- addrServer.sin_family=AF_INET;
- addrServer.sin_port=htons();//绑定端口6000
- bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));
- //Listen监听端
- listen(sockServer,);//5为等待连接数目
- printf("服务器已启动:\n监听中...\n");
- int len=sizeof(SOCKADDR);
- charsendBuf[];//发送至客户端的字符串
- charrecvBuf[];//接受客户端返回的字符串
- //会阻塞进程,直到有客户端连接上来为止
- sockClient=accept(sockServer,(SOCKADDR*)&addrClient,&len);
- //接收并打印客户端数据
- recv(sockClient,recvBuf,,);
- printf("%s\n",recvBuf);
- //关闭socket
- closesocket(sockClient);
- WSACleanup();}
- //Client客户端
- #include<winsock2.h>
- #include<stdio.h>
- #pragmacomment(lib,"ws2_32.lib")
- void main()
- {
- WSADATA wsaData;
- SOCKET sockClient;//客户端Socket
- SOCKADDR_IN addrServer;//服务端地址
- WSAStartup(MAKEWORD(,),&wsaData);
- //新建客户端socket
- sockClient=socket(AF_INET,SOCK_STREAM,);
- //定义要连接的服务端地址
- addrServer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//目标IP(127.0.0.1是回送地址)
- addrServer.sin_family=AF_INET;
- addrServer.sin_port=htons();//连接端口6000
- //连接到服务端
- connect(sockClient,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));
- //发送数据
- charmessage[]="HelloSocket!";
- send(sockClient,message,strlen(message)+,);
- //关闭socket
- closesocket(sockClient);
- WSACleanup();}
- 三次握手与四次断开<转>
- 连接握手:
- .客户端发送建立连接请求
- .服务端确认连接请求
- .客户端确认已经连接
- 以上3步完成后即可使用send recv了
- 断开握手:如果要正确断开必须经过4次握手。
- .客户端发送请求停止TCP连接请求
- .服务端收到请求后将这一个socket关闭
- .服务端发送反向请求客户端关闭socket连接
- .客户端确认服务端请求,关闭socket连接。
- TCP是一个面向连接的服务,面向连接的服务是电话系统服务模式的抽象,每一次完整的数据传输都必须经过建
- 立连接,数据传输和终止连接3个过程,TCP建立连接的过程称为三次握手,下面看一下三次握手的具本过程
- TCP三次握手过程
- 主机A通过向主机B 发送一个含有同步序列号的标志位的数据段给主机B ,向主机B 请求建立连接,通过这个数据段,
- 主机A告诉主机B 两件事:我想要和你通信;你可以用哪个序列号作为起始数据段来回应我.
- 主机B 收到主机A的请求后,用一个带有确认应答(ACK)和同步序列号(SYN)标志位的数据段响应主机A,也告诉主机A两件事:
- 我已经收到你的请求了,你可以传输数据了;你要用哪佧序列号作为起始数据段来回应我
- 主机A收到这个数据段后,再发送一个确认应答,确认已收到主机B 的数据段:"我已收到回复,我现在要开始传输实际数据了
- 这样3次握手就完成了,主机A和主机B 就可以传输数据了.
- 3次握手的特点
- 没有应用层的数据
- SYN这个标志位只有在TCP建产连接时才会被置1
- 握手完成后SYN标志位被置0
- TCP建立连接要进行3次握手,而断开连接要进行4次,这是由于TCP的半关闭造成的,因为TCP连接是全双工的(
- 即数据可在两个方向上同时传递)所以进行关闭时每个方向上都要单独进行关闭,这个单方向的关闭就叫半关闭.
- 关闭的方法是一方完成它的数据传输后,就发送一个FIN来向另一方通告将要终止这个方向的连接.当一端收到一个FIN,它必须
- 通知应用层TCP连接已终止了这个方向的数据传送,发送FIN通常是应用层进行关闭的结果.
- 4次断开
- 当主机A完成数据传输后,将控制位FIN置1,提出停止TCP连接的请求
- 主机B收到FIN后对其作出响应,确认这一方向上的TCP连接将关闭,将ACK置1
- 由B 端再提出反方向的关闭请求,将FIN置1
- 主机A对主机B的请求进行确认,将ACK置1,双方向的关闭结束.
- 由TCP的三次握手和四次断开可以看出,TCP使用面向连接的通信方式,大大提高了数据通信的可靠性,使发送数据端
- 和接收端在数据正式传输前就有了交互,为数据正式传输打下了可靠的基础
TODO:Socket的几个IO模型
Socket通讯的更多相关文章
- 闲来无事,写个基于TCP协议的Socket通讯Demo
.Net Socket通讯可以使用Socket类,也可以使用 TcpClient. TcpListener 和 UdpClient类.我这里使用的是Socket类,Tcp协议. 程序很简单,一个命令行 ...
- 试解析Tomcat运行原理(一)--- socket通讯
关于这篇文章也确实筹划了很久,今天决定开篇写第一篇,说起tomcat首先很容易联想到IIS,因为我最开始使用的就是.net技术,我第一次使用asp写学生成绩管理系统后,很茫然如何让别人都能看到或者说使 ...
- c# TCP Socket通讯基础
在做网络通讯方面的程序时,必不可少的是Socket通讯. 那么我们需要有一套既定的,简易的通讯流程. 如下: <pre name="code" class="csh ...
- Android笔记:Socket通讯常见问题
经验证的socket通讯问题 1.如果是模拟器和本机PC直接通讯,需要使用本机IP地址 而不是 10.0.2.2 如本机的静态地址为192.168.1.2 则直接使用该地址 2.接收和连接代码不能在 ...
- java socket通讯(二)处理多个客户端连接
通过java socket通讯(一) 入门示例,就可以实现服务端和客户端的socket通讯,但是上一个例子只能实现一个服务端和一个客户端之间的通讯,如果有多个客户端连接服务端,则需要通过多线程技术来实 ...
- java socket通讯(一) 入门示例
一.入门 要想学习socket通讯,首先得知道tcp/ip和udp连接,具体可参考浅谈TCP/IP 和 UDP的区别 二.示例 首先新建了一个java工程,包括两个部分,客户端SocketClient ...
- Socket网络通讯开发总结之:Java 与 C进行Socket通讯 + [备忘] Java和C之间的通讯
Socket网络通讯开发总结之:Java 与 C进行Socket通讯 http://blog.sina.com.cn/s/blog_55934df80100i55l.html (2010-04-08 ...
- 利用BlazeDS的AMF3数据封装与Flash 进行Socket通讯
前几天看到了Adobe有个开源项目BlazeDS,里面提供了Java封装AMF3格式的方法.这个项目貌似主要是利用Flex来Remoting的,不过我们可以利用他来与Flash中的Socket通讯. ...
- .Net中的Socket通讯
.NetFrameWork为Socket通讯提供了System.Net.Socket命名空间,在这个命名空间里面有以下几个常用的重要类分别是: ·Socket类 这个低层的类用于管理连接,WebReq ...
- Linux网络服务器epoll模型的socket通讯的实现(一)
准备写一个网络游戏的服务器的通讯模块,参考网上看到的一些代码,在linux下面实现一个多线程的epoll模型的socket通讯的代码,以下是第一部分多线程的切换代码: 1 #include <s ...
随机推荐
- 分享一个很早之前写的小工具DtSpyPlus
几年前写的一个获取windows窗体基本信息和屏幕取色的小工具 ,一直在用. 下载地址 http://files.cnblogs.com/dint/SpyPlus.zip
- js如何判断获取到的值是否在数组中
很简单,定义一个数组,判断下就得了. var arrayList = [1,2,3,4]; arrayList .indexOf(2); 返回0 arrayList .indexOf(6); 返回1 ...
- EF INNER JOIN,LEFT JOIN,GROUP JOIN
IQueryable<TOuter>的扩展方法中提供了 INNER JOIN,GROUP JOIN但是没有提供LEFT JOIN GROUP JOIN适用于一对多的场景,如果关联的GROU ...
- linux常用命令汇总
1. 文件及文件夹操作 1.1 修改文件名 mv abc ab 把文件名abc改为ab. 1.2 删除文件和文件夹 rm abc rm -rf abc 1.3 拷贝文件夹 格式: CP [选项] 源 ...
- A python script to check NE syncfail and get log from CIPS
#! /usr/bin/env python # -*- coding: UTF-8 -*- """The script is to check whether NE i ...
- pip和easy_install更换使用国内源
因为论文原因,需要使用python安装一些自然语言库,但是使用pip或easy_install安装包时,总是超时(中国特色搞得事:-D),没有办法,上网查资料解决问题~~,在网上找到的方法都是说更换国 ...
- 一个div里有多个a标签,改变a标签的字体颜色方法
<script type="text/javascript">var all=document.getElementById("big");var ...
- ubuntu服务管理
uRedhat 提供了chkconfig这个命令来管理系统在不同运行级别下的服务开启/关闭: chkconfig ServiceName on/off 并可以用chkconfig --list(两个杠 ...
- CSS伪类和伪元素
一.伪类 CSS伪类用于向某些选择器添加特殊的效果,在W3规范中,CSS伪类有如下几个: CSS2.1 :active:向被激活的元素添加样式(激活是指点击鼠标那一下) :focus:向拥有键盘输入焦 ...
- Visual Studio最常用、最高效的快捷键
查了一些VS编程的快捷键,大家共同学习,共同进步! 1.强迫智能感知:Ctrl+J.智能感知是Visual Studio最大的亮点之一,选择Visual Studio恐怕不会没有这个原因. 2.强迫显 ...