Linux网络编程(五)-Socket编程03:TCP客户端流程【创“流式”套接字/socket()、连服务器/connect()、读read()/recv()、写write()/send()、关闭】

一、TCP客户端函数

socket模型创建流程图

 1、创建“流式”套接字:socket()

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>

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

功能:

socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符,应用程序可以像读写文件一样用read/write在网络上收发数据,如果socket()调用出错则返回-1。

  • 对于IPv4,domain参数指定为AF_INET。
  • 对于TCP协议,type参数指定为SOCK_STREAM,表示面向流的传输协议。
  • 如果是UDP协议,则type参数指定为SOCK_DGRAM,表示面向数据报的传输协议。
  • protocol参数的介绍从略,指定为0即可。

参数:

  • domain:
    • AF_INET:这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址;
    • AF_INET6:与上面类似,不过是来用IPv6的地址;
    • AF_UNIX:本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候使用;
  • type:
    • SOCK_STREAM:这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。【只需要组应用层的数据包,底层(网络层、传输层、链路层)的包不需要人工来组,会自动组包
    • SOCK_DGRAM:这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。 【只需要组应用层的数据包,底层(网络层、传输层、链路层)的包不需要人工来组,会自动组包
    • SOCK_SEQPACKET:该协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。
    • SOCK_RAW:socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议) 【不仅需要组应用层的数据包,底层(网络层、传输层、链路层)的包也需要人工来组
    • SOCK_RDM:这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数据包的顺序
  • protocol:  
    • 传0 表示使用默认协议。
  • 返回值:
    • 成功:返回指向新创建的socket的文件描述符,
    • 失败:返回-1,设置errno

2、连服务器:connect()

#include <sys/types.h> 					/* See NOTES */
#include <sys/socket.h>

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

功能:连接服务器;

参数:

  • sockfd:socket的文件描述符【socket()函数的返回值】;
  • addr:指定服务器端地址信息,含IP地址和端口号【ipv4或ipv6类型的socket结构体的地址(参看第一章4.3 通用socket结构体)】;
  • addrlen:sizeof(addr)大小【ipv4或ipv6结构体的大小】
  • 返回值:成功返回0,失败返回-1,设置errno

二、TCP客户端代码

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

int main(int argc, char *argv[])
{
	//创建socket套接字
	int sock_fd;
	sock_fd = socket(AF_INET,SOCK_STREAM,0);
	
	// 指定服务器端地址信息
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8080);
	inet_pton(af=AF_INET, src="192.168.21.29",dst=&addr.sin_addr.s_addr); // 利用ipv4类型的ip地址转换函数,将目标服务器的点分十进制串("192.168.21.29")转为大端字节序数据,并赋值给addr结构体的sin_addr结构体的s_addr参数
	
	//连接服务器
	connect(sock_fd,(struct sockaddr *)&addr,sizeof(addr));
	
	//读写数据
	char buf[1024]="";
	while(1)
	{
		int n = read(STDIN_FILENO,buf,sizeof(buf));
		write(sock_fd,buf,n);//发送数据给服务器
		n = read(sock_fd,buf,sizeof(buf));
		write(STDOUT_FILENO,buf,n);
		printf("\n");
	
	}

	
//关闭
	close(sock_fd);

	return 0;
}

使用 NetAssist.exe 网络调试工具模拟服务端,来与自定义的客户端调试:

可以用nc命令先调试一下NetAssist服务端是否已经工作:

nc 192.168.21.29 8080

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值