C语言SOCKET学习
2015-12-19 23:12
411 查看
常见的两种套接字类型
SOCK_STREAM TCP 流格式套接字
SOCK_DGRAM UDP 数据包套接字
传输时要考虑字节序的问题,HBO (Host Byte Order) 和CPU有关。NBO(Network Byte Order) 是Big-endian的写法。
下图为socket流程图,挺好的。
![](http://img.blog.csdn.net/20151221172000036)
SOCK_STREAM TCP 流格式套接字
SOCK_DGRAM UDP 数据包套接字
基础知识: struct sockaddr // 基本不用 { unsigned short sa_family; // AF_INET char sa_data[14]; }; // AF_INET是 IPv4 网络协议的套接字类型,AF_INET6 则是 IPv6 的;而 AF_UNIX 则是 Unix 系统本地通信。 struct sockaddr_in // 大小一样,可以用sockaddr *引用 sockaddr_in { short int sin_family; // AF_INET , 存储在本机上,不需要转变为网络字节顺序 unsigned short int sin_port; //端口号,NBO struct in_addr sin_addr; // IP地址,NBO unsigned char sin_zero[8]; //需要memset初始化,一般不使用 }; struct in_addr { unsigned long s_addr; // 存放IP地址 };
传输时要考虑字节序的问题,HBO (Host Byte Order) 和CPU有关。NBO(Network Byte Order) 是Big-endian的写法。
例子:如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为 addr big-endian little-endian // 以每个字节为单位 0x0000 0x12 0xcd 0x0001 0x23 0xab 0x0002 0xab 0x34 0x0003 0xcd 0x12
下图为socket流程图,挺好的。
实际创建socket struct sockarrd_in server_addr; // 目的地的信息 memset(server_addr , 0 , sizeof(server_addr)); // 清空 server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port ); /** htons()--"Host to Network Short" htonl()--"Host to Network Long" ntohs()--"Network to Host Short" ntohl()--"Network to Host Long" **/ server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // inet_addr( ); 直接返回IP地址的网络字节格式,错误时返回-1 // printf("%s",inet_ntoa(ina.sin_addr)); 相反的调用,返回字符串形式的IP地址,重复调用覆盖上次结果。 int socket_id = socket(AF_INET, SOCK_STEAM , 0); //socket 描述符类型为 int /** 如果你要固定用某个端口,就用bind绑定,一般server端使用。 bind()的用法: 一旦拥有套接字,就可以把套接字和机器上的某个端口绑定起来。 bind就是这个作用。 struct sockaddr_in my_addr; bind(socket_id,(struct sockaddr *)my_addr,sizeof(struct sockaddr)); // 其中my_addr是sockaddr_in 类型,里面的IP地址为本机地址,端口号为要绑定的端口号。 **/ 建立连接 int err = connect(socket_id, ( struct sockaddr *)server_addr, sizeof(server_addr)); // connect();错误返回-1 发送数据 int send(int sock_id, char *str, int len, int flags); // 返回实际发送的字节数,出错返回-1 sock_id 是你想发送数据的套接字描述符(或者是调用 socket() 或者是accept() 返回的 ) str 是指向你想发送的数据的指针。len 是数据的长度,一般为strlen(str)。 把 flags 设置为 0 就可以了。 接受数据 int recv(int sock_id, char *buf, int len, unsigned int flags); // recv() 返回实际读入缓冲的数据的字节数。或者在错误的时候返回-1 sock_id 是要读的套接字描述符。buf 是要读的信息的缓冲。len 是buf的最大长度。flags 可以设置为0。 关闭套接字 close(sock_id);//任何在另一端读写套接字的企 图都将返回错误信息。 /** int shutdown(int sock_id, int how); sock_id 是你想要关闭的套接字文件描述复。how 的值是下面的其中之 一: 0 - 不允许接受 1 - 不允许发送 2 - 不允许发送和接受(和close() 一样) shutdown() 成功时返回 0,失败时返回 -1 **/ server 端: int listen(int sock_id, int backlog); //一般先bind绑定端口,再listen。 // sock_id 是被监听的套接字文件描述符。backlog 是在进入 队列中允许的连接数目。在发生错误的时候返回-1. /******下面是accept(); 的使用 #include <string.h> #include <sys/socket.h> #include <sys/types.h> main() { int sockfd, new_fd; struct sockaddr_in my_addr; struct sockaddr_in their_addr; int sin_size; sockfd = socket(AF_INET, SOCK_STREAM, 0); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(3490); my_addr.sin_addr.s_addr = "127.0.0.1"; bzero(&(my_addr.sin_zero); // 清空addr.sin_zero bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)); //绑定端口 listen(sockfd, 10); // 监听,队列最大10 sin_size = sizeof(struct sockaddr_in); // sin_size 初始化为struct sockaddr_in 的大小 new_fd = accept(sockfd, &their_addr, &sin_size); //第一个参数为被监听的套接字,their_addr存放发送请求地的信息。返回值为新建立连接的套接字信息。 // 第三个参数为accept后存入their_addr 的字节数。 }
相关文章推荐
- c语言的日常心得与总结
- 张氏读写锁,c++信号量实现
- C++:顺序容器及顺序容器适配器(stack、queue等)
- 关于C++二分搜索树的中序遍历和先序遍历
- C++:函数
- c语言常用小知识点(const、sizeof)
- c++中io流的使用
- c++匿名类—指针
- 黑马程序员-C语言-约瑟夫环
- c++静态成员与静态函数
- c++基础语法 构造函数 析构函数 类的组合
- C语言程序设计进阶 第一周1.1笔记
- c语言随机数
- C++中的inline声明
- C++将数值转换为string
- C++ 窗口加载图标
- (解题报告)HDU2024---C语言合法标识符
- 实战c++中的vector系列--正确释放vector的内存(clear(), swap(), shrink_to_fit())
- 实战c++中的vector系列--正确释放vector的内存(clear(), swap(), shrink_to_fit())
- 第一次写自己的blog--C语言基础题目--字母螺旋方阵