TCP/IP网络编程 学习笔记_2 --套接字类型与协议设置
2015-07-09 10:38
741 查看
什么是协议
先想象一下这样一个情形:如果相隔很远的两个人要展开对话,必须先决定对话方式。如果一方使用电话,那么另一方也只能使用电话,而不是书信。可以说,这里电话就是两人对话的协议,协议是对话中使用的通信规则。拓展到计算机,协议就是为了完成数据交换而定好的约定。创建套接字
1,先来看看创建套接字的函数:int socket(int domain, int type, int protocol);
成功返回文件描述符(整型),失败返回-1。
domain:协议族,type:数据传输类型,protocol:具体协议
2,下面再来分别谈谈创建套接字函数各参数意义:
协议族:奶油意大利面和番茄意大利面均属于意大利面的一种,与之类似,套接字中的协议也有分类,每一类别就称作一个协议族。即上面奶油意大利面和番茄意大利面类似协议,意大利面类似协议族。我们常用的协议族是PF_INET(IPv4互联网协议族)。
套接字类型:是指套接字数据传输的方式,下面介绍2种具有代表性的数据传输方式:
一:面向连接的套接字(SOCK_STREAM),这个和两个工人用传送带传输与接收物品类似,它有以下特性:传输过程中数据不会丢失,按序传输数据,没有数据边界,连接必须一一对应。
注释:没有数据边界是指,数据的发送次数与接收次数没有直接关系,不一定要相等。其实现原理就是在发送与接收端各用了个缓冲区,发送与接收端都是只管从缓冲区里取和拿数据,不直接相关。而且就算某个缓冲区满了也不会丢失数据,因为面向连接的套接字会根据接收端的状态来传输数据,如果缓冲区满了,它会自动停止传输。
二:面向消息的套接字(SOCK_DGRAM),这个就类似快递送包裹,有以下特点:强调传输速度不必按序传输,数据可能丢失,每次传输数据大小有限制,有数据边界(传输次数与接收次数要一一对应),不存在连接的概念。
协议:socket()第三个参数就是具体协议的选择,如:
“IPv4协议族中面向连接的套接字”
int tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
因为IPv4协议族中面向连接的套接字的具体协议只有一种就是IPPROTO_TCP,所以第三个参数我们也可以简写成0。这种套接字我们称为TCP套接字。
“IPv4协议族中面向消息的套接字”
int udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
同上,这里第三个参数也可以写成0。这种套接字我们称为UDP套接字。
代码示例
下面是一个tcp套接字的实例,从中就可以看出tcp套接字没有数据边界。服务端
// // main.cpp // hello_server // // Created by app05 on 15-7-6. // Copyright (c) 2015年 app05. All rights reserved. // #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } int main(int argc, const char * argv[]) { int serv_sock; int clnt_sock; struct sockaddr_in serv_addr; struct sockaddr_in clnt_addr; socklen_t clnt_addr_size; char message[] = "Hello World!"; if(argc != 2) { printf("Usage:%s <port>\n", argv[0]); exit(1); } /*IPv4协议族中面向连接的套接字(tcp套接字),因为这种类型下的具体协议只有一种(IPPROTO_TCP), 所以第三个参数可以简写为0*/ serv_sock = socket(PF_INET, SOCK_STREAM, 0); if(serv_sock == -1) error_handling("socket() error"); memset(&serv_addr, 0, sizeof(serv_addr)); 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"); clnt_addr_size = sizeof(clnt_addr); //如果没有收到请求,则不返回,只到有连接请求为止 clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_size); if(clnt_sock == -1) error_handling("accept() error"); //message数组内容一次性发送 write(clnt_sock, message, sizeof(message)); close(clnt_sock); close(serv_sock); return 0; }
客服端
// // main.cpp // hello_client // // Created by app05 on 15-7-6. // Copyright (c) 2015年 app05. All rights reserved. // #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } int main(int argc, const char * argv[]) { int sock; struct sockaddr_in serv_addr; char message[30]; int str_len = 0; int idx = 0, read_len = 0; if(argc != 3) { printf("Usage: %s <IP> <port>\n", argv[0]); exit(1); } sock = socket(PF_INET, SOCK_STREAM, 0); if(sock == -1) error_handling("socket() error"); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(argv[1]); serv_addr.sin_port = htons(atoi(argv[2])); if(connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1) error_handling("connect() error"); //每次只接收一个字节(服务端一次性发送,客服端多次接收,验证tcp套接字没有数据边界) while (read_len = read(sock, &message[idx++], 1)) { if(read_len == -1) error_handling("read() error!"); str_len += read_len; } printf("Message from server: %s \n", message); printf("Function read call count: %d \n", str_len); close(sock); return 0; }
相关文章推荐
- android存储之网络存储和数据库存储
- TCP_TW_REUSE设置
- 渠道系统和 OA系统待办事项接口
- boost::asio的http client应用笔记
- boost::asio的http client应用笔记
- python做一个http接口测试框架
- 给微商翻案 一个150人的生意有得玩
- retrofit第一次的网络请求eofException错误原因及解决
- Java / Android 基于Http的多线程下载的实现
- Android开发 通过httpURL获取图片
- HTTP请求及应答
- HttpURLConnection 和 AndroidHttpClient
- 自己动手写网络爬虫1
- Https如何保证安全
- NAT( 网络地址转换) 实现
- Netty解决半包(TCP粘包/拆包导致)读写问题
- 网络编程——Java基础
- Unity3D中的http通信
- http://www.csdn.net/article/2013-03-06/2814373-baas-for-mobile-backend-development
- 网络原理,以及对VMware Workstation虚拟网络VMnet0、VMnet1、VMnet8的图解