概述
一、TCP回顾
1、面向连接的流式协议;可靠、出错重传、且每收到一个数据都要给出相应的确认
2、通信之前需要建立链接
3、服务器被动链接,客户端是主动链接
1.1、TCP与UDP的差异
1.2、TCP和UDP流程对比
从这两副图,我们不难发现,TCP比UDP多几个函数,其中最明显的是TCP服务器,需要监听和等待客户端请求连接,而TCP客户端,需要向服务器请求连接成功,才可以通信。
二、TCP编程流程
服务器:
第一步:创建套接字 socket()
第二步:将套接字与服务器网络信息结构体绑定 bind()
第三步:将套接字设置为监听状态 listen()
第四步:阻塞等待客户端的连接请求 accept()
第五步:进行通信 recv()/send()
第六步:关闭套接字 close()
客户端:
第一步:创建套接字 socket()
第二步:发送客户端连接请求 connect()
第三步:进行通信 send()/recv()
第四步:关闭套接字 close()
三、函数的学习与参数的设置
3.1、TCP编程——socket函数
头文件
#include <sys/types.h>
#include <sys/socket.h>
函数:int socket(int domain, int type, int protocol);
功能:创建一个套接字,返回一个文件描述符
参数:
domain:通信域,协议族
AF_UNIX 本地通信AF_INET ipv4网络协议
AF_INET6 ipv6网络协议
AF_PACKET 底层接口
type:套接字的类型
SOCK_STREAM 流式套接字(用于TCP)
SOCK_DGRAM 数据报套接字(用于UDP)
SOCK_RAW 原始套接字(用于链路层)
protocol:附加协议,如果不需要,则设置为0
返回值:
成功:文件描述符
失败:‐1
3.1.1、案例:创建一个TCP套接字
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
int main(int argc ,char *argv[])
{
int sockfd;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("fail to sockfd");
exit(1);
}
printf("TCP:sockfd= %dn",sockfd);
return 0;
}
3.2、 TCP编程——connect函数
头文件
#include <sys/types.h>
#include <sys/socket.h>
函数:int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:给服务器发送客户端的连接请求
参数:
sockfd:文件描述符,socket函数的返回值
addr:要连接的服务器的网络信息结构体(需要自己设置)
addrlen: addr的长度
返回值:
成功: 0
失败:‐1
头文件:
#include <netinet/in.h>
函数结构体:
struct sockaddr_in
{
sa_family_t sin_family; //协议族 2字节
in_port_t sin_port; //端口号 2字节
struct in_addr sin_addr; //ip地址 4字节
char sin_zero[8] //填充,不起什么作用 8字节
};struct in_addr
{
in_addr_t s_addr; //ip地址 4字节
};
注意:
1、connect建立连接之后不会产生新的套接字
2、连接成功后才可以开始传输TCP数据
3、头文件:#include <sys/socket.h>
3.3、TCP编程——send函数
头文件
#include <sys/types.h>
#include <sys/socket.h>
函数:ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:发送数据
参数:
sockfd:文件描述符
buf:发送的数据
len:buf的长度
flags:标志位
0 阻塞
MSG_DONTWAIT 非阻塞
返回值:
成功:发送的字节数
失败:‐1
注意:不能用TCP协议发送0长度的数据包
3.4、TCP编程——recv函数
头文件
#include <sys/types.h>
#include <sys/socket.h>
函数:ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:接收数据
参数:
sockfd:文件描述符
客户端:socket函数的返回值
服务器:accept函数的返回值buf:保存接收到的数据
len:buf的长度
flags:标志位
0 阻塞
MSG_DONTWAIT 非阻塞
返回值:
成功:接收的字节数
失败:‐1
注意: 如果发送端关闭文件描述符或者关闭进程,则recv函数会返回0
四、客户端发送信息给服务器(服务器 使用用 “网络助手”代替)
4.1、客户端代码
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define N 1024
int main(int argc ,char *argv[])
{
if(argc<3)
{
printf("fail ,lose ip portn");
exit(1);
}
int sockfd;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("fail to sockfd");
exit(1);
}
// printf("TCP:sockfd= %dn",sockfd);
struct sockaddr_in mysockaddr;
mysockaddr.sin_family=AF_INET;
mysockaddr.sin_port=htons(atoi(argv[2]));
mysockaddr.sin_addr.s_addr=inet_addr(argv[1]);
socklen_t addrlen= sizeof(mysockaddr);
if(connect(sockfd,(struct sockaddr*)&mysockaddr,addrlen)==-1)
{
perror("fail to connect");
exit(1);
}
char buf[N]="";
fgets(buf,N,stdin);
if(send(sockfd,buf,N,0)==-1)
{
perror("fail to send");
exit(1);
}
char text[500]="";
if(recv(sockfd,text,50,0)==-1)
{
perror("fail to recv");
exit(1);
}
printf("from server: %sn",text);
close(sockfd);
return 0;
}
运行结果
最后
以上就是冷酷银耳汤为你收集整理的TCP网络编程的全部内容,希望文章能够帮你解决TCP网络编程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复