socket套接字及TCP的实现框架

一、socket套接字 

1.体系结构的两种形式

(1)网络的体系结构是计算机网络的各层及其协议的集合,就是这个计算机网络及其构件所应完成的功能的精确定义(不涉及实现)。

(2)实现是遵循这种体系结构的前提下,用何种硬件或软件完成这些功能的问题。
2.几种常见的网络编程接口

(1)Berkeley UNLX操作系统定义了一种API,它又称为套接字接口。

(2)微软公司在其操作系统中采样了套接字接口API,形成了一个稍微不同的API,并称之为Windows Socket。

(3)AT&T为其UNIX系统V定义了一种API,简写为TLI。

 二、socket常用API介绍

/*创建套接字*/
int socket(int domain, int type, int protocol); 
/*绑定通信结构体*/
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*监听套接字*/
int listen(int sockfd, int backlog);
/*处理客户端发起的连接,生成新的套接字*/
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
/*向服务器发起连接请求*/
int connect(int sockfd, const struct sockaddr *addr,  socklen_t addrlen);

1.三元组【IP地址,端口,协议】

        IP地址:标识计算机

        端口号:标识计算机当中的进程

        协议:指定数据传输的方式

//通用地址族结构体

struct sockaddr {
    sa_family_t sa_family;
    char      sa_data[14];
}
/*地址族结构体*/
struct sockaddr_in {
    sa_family_t sin_family;
    in_port_t sin_port;
    struct in_addr sin_addr;
};
struct sockaddr {
    uint32_t s_addr;
};
/*地址族结构体*/
struct sockaddr_in6 {
    sa_family_t sin6_family;
    in_port_t sin6_port;
    uint32_t sin6_flowinfo;
    struct in_addr sin_addr;
    uint32_t sin6_scope_id;
};
struct sockaddr {
    unsigned char s6_addr[16];
};

//sa_family

AF_UNIX      使用本地域套接字的地址结构,用于本地通信

AF_INET       使用IPv4的通信地址结构

AF_INET6     使用IPv6的通信地址结构

....

2.套接字类型

(1)流式套接字 (SOCK_STREAM) 提供可靠的、面向连接的通信流;它使用TCP,从而保证数据传输的可靠性和顺序性

(2)数据报套接字 (SOCK_DGRAM) 定义了一种不可靠、面向无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议UDP

(3)原始套接字(SOCK_RAW) 允许直接访问底层协议,如IP或ICMP,它功能强大但使用较为不便,主要用于协议开发。

三、TCP通信的实现过程

listen函数设置长度

四、实现TCP通信

1.socket函数与通信域

#include <sys/types.h>

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

-domain: 指定通信域(通信地址族);

-type: 指定套接字类型;

-protocol: 指定协议;

(1)套接字类型与协议

-type: 指定套接字类型

TCP唯一对应流式套接字,所以选择SOCK_STREAM(数据报套接字:SOCK_DGRAM)

-protocol: 指定协议

流式套接字唯一对应TCP,所以无需要指定协议,设为0即可。

 2.bind函数与通信结构体

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

-sockfd:socket函数生成的套接字

-addr:通信结构体

-addrlen:通信结构体的长度

 (1)IPv4地址族结构体

struct sockaddr_in {

sa_family_t    sin_family; /* 地址族: AF_INET */

in_port_t      sin_port;   /* 网络字节序的端口号 */

struct in_addr sin_addr;   /*IP地址结构体 */

};

/* IP地址结构体 */

struct in_addr {

uint32_t       s_addr;     /* 网络字节序的IP地址 */

};

(2)通用地址族结构体

struct sockaddr {

               sa_family_t sa_family;

               char        sa_data[14];

           }

示例:为套接字fd绑定通信结构体addr

addr.sin_family = AF_INET;//地址族 IPv4

addr.sin_port = htons(5001);//网络字节序的端口号,主机字节序转网络字节序

addr.sin_addr.s_addr = 0;//网络字节序的IP地址,本网络的本主机

bind(fd, (struct sockaddr *)&addr, sizeof(addr) );

3.listen函数与accept函数

/*监听套接字*/

int listen(int sockfd, int backlog);

/*处理客户端发起的连接,生成新的套接字*/

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

-sockfd: 函数socket生成的套接字

-addr:客户端的地址族信息

-addrlen:地址族结构体的长度

服务端示例:实现TCP通信

ifconfig命令,查看本地环回地址127.0.0.1

nc 127.0.0.1 5001 实现通信

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 5001
#define BACKLOG 5

int main(){
	int fd,newfd;
	char buf[BUFSIZ] = {};//BUFSIZ 8142个字节
	struct sockaddr_in addr;
	/*创建套接字*/
	fd = socket(AF_INET, SOCK_STREAM, 0);
	if(fd < 0){
		perror("socket");
		exit(0);
	}
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = 0;
	/*绑定通信结构体*/
	if(bind(fd,(struct sockaddr *)&addr, sizeof(addr)) == -1){

		perror("bind");	
		exit(0);
	}
	/*设置套接字为监听模式*/
	if(listen(fd, BACKLOG) == -1){
		perror("listen");
		exit(0);
	}
	/*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/
	newfd = accept(fd, NULL, NULL);
	if(newfd < 0){
		perror("accept");
		exit(0);
	}
	printf("BUFSIZ = %d\n", BUFSIZ);
	read(newfd, buf, BUFSIZ);
	printf("buf = %s\n", buf);
	close(fd);
	return 0;
}

运行结果:

示例:服务器客户端代码

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 5001
#define BACKLOG 5
#define STR "Hello World!"

int main(int argc, char *argv[])
{
	int fd;
	struct sockaddr_in addr;
	/*创建套接字*/
	fd = socket(AF_INET, SOCK_STREAM, 0);
	if(fd < 0){
		perror("socket");
		exit(0);
	}
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	/*向服务端发起连接请求*/
	if(connect(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){
		perror("connect");
		exit(0);
	}
	write(fd, STR, sizeof(STR) );
	printf("STR = %s\n", STR);
	close(fd);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
感谢大家对北风之神SOCKET框架的支持。鼓励。下面是北风之神 3.1的更新内容: 修正BUG: 1.ZYSocketSuper 读取 配置文件的最大连接数 读错问题。 2.ZYSocketSuper 无法断开客户端的问题。 3.BuffList 数据包解析丢失问题。 4.例1,例2.客户端断开忘记释放调用SOCKET.CLOSE()的问题 新增功能 1.添加了一个ReadBytes 构造函数,此函数实现了在数据包在读取前需要回调的方法传入。(可以用来解密,解压缩 等功能) 2.添加了一个BufferFormat 类的构造,此函数实现了在数据包在生成前需要回调的方法传入。(可以用来加密,压缩 等功能) 3.添加了BufferFormat.FormatFCA(object o,FDataExtraHandle dataExtra)静态方法。可以用来在类格式化成数据包的时候进行加密压缩等功能 4.添加了ZYSocket.Security 命名空间,里面有传统的AES,DES算法的加解密类 5.添加了ZYSocket.Compression命名空间,里面有通过Deflate算法压缩类 6.开发了ReadBytes.Data属性,为ReadBytes里面的BYTE[]对象。值得注意的是 ReadBytes.Length为数据包原始长度,如果要得到解压缩后的数据包长度,请访问ReadByte.Data.length 新增代码 加解密实例测试 项目:演示了 AES DES 以及Deflate 的使用方法。 例3 - 例2的加密版 项目:就是讲例2通过DES 加密进行通讯的例子 连接测试工具 项目:很多朋友问我要连接数量测试工具。我一起的真的丢了。找不到了。所以重新写了一个 例4 项目:好多人让我写一个发送文件的例子,现在能如愿以偿了 by luyikk@126.com BLOG:http://blog.csdn.net/luyikk QQ:547386448

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值