Socket-TCP/UDP浅析
来源:互联网 发布:p2p数据分析报告 编辑:程序博客网 时间:2024/05/16 07:57
TCP与UDP传输协议浅析
对于这个问题,相信刚接触开发的人遇到的比较频繁,很多开发术语说出来的知识概念显得很高深,很难,其实不是,等你自己打通一条UDP/TCP通信,实现传输的时候,发现还是很易使用的。
二者差异:
1、TCP面向连接;UDP是无连接的。
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低。
4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
5、TCP首部开销20字节;UDP的首部开销小,只有8个字节。
这里列举了几条,其实要详述差异还有很多很多,其内部复杂的通信实现,作为一位普通的开发人员不需要了解,我们只要达到可以在适合的场合,使用适合的通信方式即可。(通俗的理解:TCP似一条河流,要想流通,必须建立河道,传输是不间断的发送流,而且会出现阻塞。但毕竟是河道是唯一的,通信安全可靠,而UDP是将数据分包,每次会发送一个包出去,到指定的sever和port,可以是一,也可以是多,不需要建立不间断连接,所以可靠性相对低一些(我发了10条,你网络不好,接收7条,发送到仍然会认为数据发送完毕))。
1、UDP实现
{ struct sockaddr_in si_other; int _socket,addled; char buf[BUFLEN];//存储接收状态}//用于设置发送超时static sigjmp_buf recv_timed_out;void timeout_handler (int signum){ signal(SIGALRM, SIG_DFL); siglongjmp(recv_timed_out, 1);}
//socket初始化sever为ip地址,port为端口号addlen = sizeof(si_other);memset((char *) &si_other, 0, sizeof(si_other));si_other.sin_family = AF_INET;si_other.sin_port = htons(port);inet_aton([server UTF8String] , &si_other.sin_addr);_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//发送data数据到指定sever- (NSString *)sendTheMessage:(NSData *)data{ //发送数据 if (_socket<0) { NSLog(@"failed to create socket"); } NSString *message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; long status_send = sendto(_socket, [message UTF8String], strlen([message UTF8String]), 0, (struct sockaddr *)&si_other, addlen); if (status_send == -1) { NSLog(@"failed to send"); } //发送超时设置 struct timeval timeout = {5,0}; setsockopt(_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval)); //接收返回状态buf memset(buf,'\0', BUFLEN); long status_receive = recvfrom(_socket, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &addlen); if (status_receive == -1) { NSLog(@"failed to receive ,time out!"); } return [NSString stringWithUTF8String:buf];}
以上就是个简单的UDP实现,发送什么,返回什么,都是开发与后台之间共同决定的。
2、TCP实现
static const unsigned int READ_BUFFER_SIZE = 1024;@interface TCP (){ struct sockaddr_in serverAddress; int _socket; unsigned char * _readBuffer; volatile BOOL _isConnected; NSString * _className; volatile BOOL _isReleasedBuffer;}@end@implementation TCP//初始化sever的基础信息- (instancetype)initWithAddress:(NSString *)address Port:(int)port{ self = [super init]; if (self) { serverAddress.sin_len = sizeof(struct sockaddr_in); serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(port); serverAddress.sin_addr.s_addr = inet_addr([address UTF8String]); bzero(&(serverAddress.sin_zero),8); _readBuffer = malloc(READ_BUFFER_SIZE); bzero(_readBuffer, 0); _isReleasedBuffer = NO; _className = @"Socket"; } return self;}//建立socket,设置读写延时,建立client和sever的连接- (BOOL)connect{ //init socket _socket = socket(AF_INET, SOCK_STREAM, 0); struct timeval resvTimeoutPramaters; struct timeval sendTimeoutParameters; //set read timeout resvTimeoutPramaters.tv_sec = 3; resvTimeoutPramaters.tv_usec = 1500; int errorCode = setsockopt(_socket, SOL_SOCKET, SO_RCVTIMEO, &resvTimeoutPramaters, sizeof(struct timeval)); if(errorCode < 0){ NSLog(@"[%@] setsockopt revtimeo error is %d", _className, errorCode); return NO; } //set send timeout sendTimeoutParameters.tv_sec = 3; sendTimeoutParameters.tv_usec = 1500; errorCode = setsockopt(_socket, SOL_SOCKET, SO_SNDTIMEO, &sendTimeoutParameters, sizeof(struct timeval)); if(errorCode < 0){ NSLog(@"[%@] setsockopt sedtimeo error is %d", _className, errorCode); return NO; } // in case of SIGPIPE signal happens. int set = 1; setsockopt(_socket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); // check whether a socket is established succesfully if(_socket == -1){ NSLog(@"[%@] socket created failed", _className); return NO; } // try to connect if (connect(_socket, (struct sockaddr *)&serverAddress, sizeof(struct sockaddr_in))==0) { _isConnected = YES; return YES; } NSLog(@"[%@] socket connected failed", _className); return NO;}//关闭socket- (void)closeSocket{ @synchronized(self){ close(_socket); if(!_isReleasedBuffer){ free(_readBuffer); _isReleasedBuffer = YES; } }}
//TCP是面向连接的,使用send发送数据char buf[1024];do { printf("input message:"); scanf("%s",buf); send(fd, buf, 1024, 0);} while (strcmp(buf, "exit")!=0);
socket调用库函数主要有:
创建套接字
Socket(af,type,protocol)
建立地址和套接字的联系(sever端使用)
bind(sockid, local addr, addrlen)
服务器端侦听客户端的请求(sever段使用)
listen( Sockid ,quenlen)
建立服务器/客户端的连接 (面向连接TCP)
客户端请求连接
Connect(sockid, destaddr, addrlen)
服务器端等待从编号为Sockid的Socket上接收客户连接请求
newsockid=accept(Sockid,Clientaddr, paddrlen)
发送/接收数据
面向连接:(TCP连接发送使用)
send(sockid, buff, bufflen) recv( )
面向无连接:(UDP无连接发送使用)
sendto(sockid,buff,…,addrlen) recvfrom( )
释放套接字
close(sockid)
socket的简单使用就这些,其内部的理论在各大网站上都有描述,会对C方法内部的具体过程进行详细的讲解,这里就不做描述了。github上的socket开源项目,这个可以直接使用。
- Socket-TCP/UDP浅析
- SOCKET,TCP/UDP,HTTP,FTP浅析
- SOCKET, TCP/UDP, HTTP, FTP 浅析
- SOCKET, TCP/UDP, HTTP, FTP 浅析
- TCP和UDP浅析
- TCP,UDP浅析
- 浅析TCP与UDP
- socket,tcp,udp
- TCP-UDP Socket
- TCP UDP Socket流程
- Socket与TCP、UDP
- HTTP、TCP、UDP、Socket
- TCP-UDP Socket
- TCP-UDP Socket
- tcp/udp Socket图解
- TCP-UDP Socket
- UDP、TCP、socket区别
- TCP/IP、UDP、Socket
- 生活杂记
- Android安全专项-利用androguard分析微信
- 深入浅出Nginx之七【重要知识补充】
- pku1795 DNA Laboratory 状压DP
- Hbase Sql 层 Phoenix 的三个特性Row timestamp, Sequences 和 Salted Tables
- Socket-TCP/UDP浅析
- 多个 Kylin 服务
- AngularJS 指令的 Scope (作用域)
- cas 单点登录问题
- 基于FastDfs的分布式文件存储系统设计
- 互联网+农业的机遇与挑战
- 优先队列及最小堆最大堆
- Extjs4----anchor布局
- 把Android项目迁移到Android Studio常见的错误