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 ...
随机推荐
- MVC系列1-MVC基础 (ASP.NET)
终于决定写一个系列的文章了,最开始其实是准备写一下WPF的,因为我这两年一直在做WPF,对WPF的喜爱自然是无以言表.但是由于我所在的地区对WPF的普及不是很广泛,所以,被迫又开始做起来web,但是我 ...
- Innodb 表空间传输迁移数据
在mysql5.5之前,mysql实例中innodb引擎表的迁移是个头疼的问题,要么使用mysqldump导出,要么使用物理备份的方法,但是在mysql5.6之后的版本中,可以使用一个新特性,方便地迁 ...
- jQuery Mobile应用之火车票查询
效果图: 在CMD中输入如下代码 corsproxy (前提是有node.js环境,并先安装corsproxy) html: <!DOCTYPE html> <html> &l ...
- 求排列组合数C(n,m) φ(゜▽゜*)♪
我们可以先预处理出1~n的阶乘以及阶乘的逆元: 对于阶乘的逆元,我们可以直接由费马小定理,用快速幂求出: (吐槽快速幂…………一定要开long long,不然会爆零
- Is the Information Reliable? -POJ2983差分约束
Time Limit: 3000MS Memory Limit: 131072K Description The galaxy war between the Empire Draco and the ...
- [iOS][issis] requestLocationWithReGeocode AMapLocationErrorDomain Code=5 "取消"
Tip: IOS 使用高德地图一次定位 (在该博客找到了解决答案) 在定位时如果出现下面这个Error,说明你的locationManager没有设置成全局变量,导致locationManager提 ...
- React组件库
图表组件库:Recharts(React和D3构建的图表库) UI组件库:react-bootstrap
- Cocos2d-x 核心概念 - Node中的重要操作
作为跟类,Node有很多的重要的函数 local childNode = cc.Node:create() --创建节点 node:addChildNode(childNode,0,123) --创建 ...
- Mac下搭建android开发环境
1> 下载JDK, jdk-8u71-macosx-x64 2> 下载android studio
- dubbo & zookeeper & springMVC
一.安装准备 1.环境简介 名称 版本 OS Mac OS X 10.11.5 JDK 1.8.0_51 dubbo 2.5.4 tomcat 8.0.35 Zookeeper 3.4.8 maven ...