tcp的socket编程
Ⅰ socket编程·send和recv
socket的send和recv是同时支持TCP和UDP的。从这两个函数的设计可以看出,协议简单来说就是读写数据。
socket的选项是 SOCK_STREAM 。
send的返回值>0时,表示实际发送了多少字节。 注意: 只是到系统缓存里,系统决定什么时候会发送这些数据。
send的返回值==0时,这个在send空串时会发生,是正常的。
send的返回值<0时(只会等于-1吧),需要检查errno,败册芹当 errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN 时,连接正常,可以稍后再试。其他的就是连接异常了。
recv的返回值>0时,表示实际接受到多少字节。
recv的返回值==0时, 表示连接断开 ,也就是收到了FIN或者RST。
recv的返回值<0时,检查errno,和send类似。
socket的选项是 SOCK_DGRAM 。
send的返回值>0时,姿搏 返回值应该等于发送的数据长察毕度 。如果send的数据大于MTU,会在IP层分片,到达目标机器后IP层重组。
send的返回值==0时,这个只在发送空串时出现。 注意: 真的会发送空数据的。
send的返回值<0时,检查errno,确定连接是否还正常。一般不会发生吧,UDP的send是直接发送出去的。
recv的返回值>0时, 收到一个完整的数据包 。这个完整性是有IP层保证的。
recv的返回值==0时, 收到空包,这和TCP有很大不同 。
recv的返回值<0时,检查errno,确定socket是否正常。
PS: UDP还有两个函数 sendto 和 recvfrom 。客户端在调用connect后,才能用 send 和 recv , 服务器端只能用 sendto 和 recvfrom 。
UDP无连接,无顺序,自然不能代替TCP。
TCP是流式协议,需要应用层确认数据是否接受完整,也不能代替UDP。
应用要同时支持两种协议,得在上层做包装。有个KCP,使用UDP模拟TCP。
Ⅱ Python 之 Socket编程(TCP/UDP)
socket(family,type[,protocal]) 使用给定的地址族、套接字类型、协议编号(默认为0)来创建套接字。
有效的端口号: 0~ 65535
但是小于1024的端口号基本上都预留给了操作系统
POSIX兼容系统(如Linux、Mac OS X等),在/etc/services文件中找到这些预留端口与的列表
面向连接的通信提供序列化、可靠的和不重复的数据交付,而没有记录边界。意味着每条消息都可以拆分多个片段,并且每个消息片段都能到达目的地,然后将它们按顺序组合在一起,最后将完整的信息传递给等待的应用程序。
实现方式(TCP):
传输控制协议(TCP), 创建TCP必须使用SOCK_STREAM作为套接字类型
因为这些套接字(AF_INET)的网络版本使用因特网协议(IP)来搜寻网络中的IP,
所以整个系统通常结合这两种协议(TCP/IP)来进行网络间数据通信。
数据报类型的套接字, 即在通信开始之前并不需要建议连接,当然也无法保证它的顺序性、可靠性或重复性
实现方式(UDP)
用户数据包协议(UDP), 创建UDP必须使用SOCK_DGRAM (datagram)作为套接字类型
它也使用因特网来寻找网络中主机,所以是UDP和IP的组合名字UDP/IP
注意点:
1)TCP发送数据时,已建立好TCP连接,所以不需要指定地址。UDP是面向无连接的,每次发送要指定是发给谁。
2)服务端与客户端不能直接发送列表,元组,字典。需要字符串化repr(data)。
TCP的优点: 可靠,稳定 TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。
TCP的缺点: 慢,效率低,占用系统资源高,易被攻击 TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU、内存等硬件资源。 而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。
什么时候应该使用TCP : 当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。 在日常生活中,常见使用TCP协议的应用如下: 浏览器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、SSH QQ文件传输.
UDP的优点: 快,比TCP稍安全 UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。但UDP也是无法避免攻击的,比如:UDP Flood攻击……
UDP的缺点: 不可靠,不稳定 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。
什么时候应该使用UDP: 当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。 比如,日常生活中,常见使用UDP协议的应用如下: QQ语音 QQ视频 TFTP ……
Ⅲ 采用tcp协议,使用socket编程,编写程序完成客户端发送消息给服务端,服务端接到消息后,再发
服务端代码:
/*server.c*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
#define PORT 4321
#define BUFFER_SIZE 1024
#define MAX_QUE_CONN_NM 5
int main()
{
struct sockaddr_in server_sockaddr, client_sockaddr;
int sin_size, recvbytes;
int sockfd, client_fd;
char buf[BUFFER_SIZE];
/*建立socket连接*/
if ((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1)
{
perror("socket");
exit(1);
}
printf("Socket id = %d\n",sockfd);
/*设置sockaddr_in 结构体中相关参数*/
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
server_sockaddr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_sockaddr.sin_zero), 8);
int i = 1;/* 使得重复使用本地地址与套接字进行绑定 */
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
/*绑定函数bind*/
if (bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr))== -1)
{
perror("bind");
exit(1);
}
printf("Bind success!\n");
/*调用listen函数*/
if (listen(sockfd, MAX_QUE_CONN_NM) == -1)
{
perror("listen");
exit(1);
}
printf("Listening....\n");
/*调用accept函数,等待客户端的连接*/
if ((client_fd = accept(sockfd, (struct sockaddr *)&client_sockaddr, &sin_size)) == -1)
{
perror("accept");
exit(1);
}
/*调用recv函数接收客户端的请求*/
memset(buf , 0, sizeof(buf));
if ((recvbytes = recv(client_fd, buf, BUFFER_SIZE, 0)) == -1)
{
perror("recv");
exit(1);
}
printf("Received a message: %s\n", buf);
if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1)
{
perror("send");
exit(1);
}
close(sockfd);
exit(0);
}
客户端:
/*client.c*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#define PORT 4321
#define BUFFER_SIZE 1024
int main(int argc, char *argv[])
{
int sockfd, sendbytes;
char buf[BUFFER_SIZE];
struct hostent *host;
struct sockaddr_in serv_addr;
if(argc < 3)
{
fprintf(stderr,"USAGE: ./client Hostname(or ip address) Text\n");
exit(1);
}
/*地址解析函数*/
if ((host = gethostbyname(argv[1])) == NULL)
{
perror("gethostbyname");
exit(1);
}
memset(buf, 0, sizeof(buf));
sprintf(buf, "%s", argv[2]);
/*创建socket*/
if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
perror("socket");
exit(1);
}
/*设置sockaddr_in 结构体中相关参数*/
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(serv_addr.sin_zero), 8);
/*调用connect函数主动发起对服务器端的连接*/
if(connect(sockfd,(struct sockaddr *)&serv_addr, sizeof(struct sockaddr))== -1)
{
perror("connect");
exit(1);
}
/*发送消息给服务器端*/
if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1)
{
perror("send");
exit(1);
}
if ((recvbytes = recv(sockfd, buf, BUFFER_SIZE, 0)) == -1)
{
perror("recv");
exit(1);
}
close(sockfd);
exit(0);
}
Ⅳ iOS开发网络篇—Socket编程
一、网络各个协议:TCP/IP、SOCKET、HTTP等
网络七层由下往上分别为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
其中物理层、数据链路层和网络层通常被称作媒体层,是网络工程师所研究的对象;
传输层、会话层、表示层和应用层则被称作主机层,是用户所面向和关心的内容。
http协议对应于应用层
tcp协议对应于传输层
ip协议对应于网络层
三者本质上没有可比性。 何况HTTP协议是基于TCP连接的。
TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。
我 们在传输数据时,可以只使用传输层(TCP/IP),但是那样的话,由于没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用应用层 协议,应用层协议很多,有HTTP、FTP、TELNET等等,也可以自己定义应用层协议。WEB使用HTTP作传输层协议,以封装HTTP文本信息,然 后使用TCP/IP做传输层协议将它发送到网络上。Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
二、Http和Socket连接区别
相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助。
2.1、TCP连接
要想明白Socket连接,先要明白TCP连接。手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接。TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。
建立起一个TCP连接需要经过“三次握手”:
第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握
手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连
接之前,TCP
连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客
户端交互,最终确定断开)
2.2、HTTP连接
HTTP协议即超文本传送协议(HypertextTransfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。
HTTP连接最显着的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。
2)在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。
由
于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。通常的
做法是即时不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客
户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开。
三、SOCKET原理
3.1、套接字(socket)概念
套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
应
用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个
TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应
用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
3.2 、建立socket连接
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。
套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
连
接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户
端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
3.3、SOCKET连接与TCP连接
创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。
3.4、Socket连接与HTTP连接
由
于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用
中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致
Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。
而HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。
很
多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送给
客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可以
保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。
这里我们使用Socket实现一个聊天室的功能,关于服务器这里的就不介绍了
@interfaceViewController (){
NSInputStream *_inputStream;//对应输入流
NSOutputStream *_outputStream;//对应输出流
}
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *inputViewConstraint;
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *chatMsgs;//聊天消息数组
@end
懒加载这个消息数组
//从主运行循环移除
//1.建立连接
//定义C语言输入输出流
//把C语言的输入输出流转化成OC对象
//设置代理
//把输入输入流添加到主运行循环
//不添加主运行循环 代理有可能不工作
//打开输入输出流
//登录
//发送用户名和密码
//在这里做的时候,只发用户名,密码就不用发送
//如果要登录,发送的数据格式为 "iam:zhangsan";
//如果要发送聊天消息,数据格式为 "msg:did you have dinner";
//登录的指令11NSString *loginStr =@"iam:zhangsan";
//把Str转成NSData
//建立一个缓冲区 可以放1024个字节
//返回实际装的字节数
//把字节数组转化成字符串
//从服务器接收到的数据
//聊天信息
//刷新表格
//发送数据
//发送完数据,清空textField
//数据多,应该往上滚动
}
//监听键盘
//获取窗口的高度
//键盘结束的Frm
//获取键盘结束的y值