您现在的位置是:首页 >其他 >网络编程——TCP编程网站首页其他
网络编程——TCP编程
流程
在C语言中进行TCP编程的一般步骤如下:
(1)包含头文件:
在代码中包含必要的头文件,以便使用TCP编程所需的函数和数据类型。通常情况下,你需要包含 <sys/socket.h>、<netinet/in.h> 和 <arpa/inet.h>。
(2)创建套接字:
使用 socket() 函数创建一个套接字,该套接字将用于网络通信。套接字是一个整数值,它表示一个打开的文件描述符,用于在网络上发送和接收数据。
(3)设置地址和端口:
创建一个 struct sockaddr_in 结构体,并设置其中的成员变量,包括地址和端口号。这个结构体用于指定服务器的地址和端口。
(4)绑定套接字:
使用 bind() 函数将套接字绑定到指定的地址和端口上。这将使服务器能够监听指定的端口并接受客户端的连接。
(5)监听连接:
使用 listen() 函数开始监听连接请求。这将使服务器进入被动等待状态,等待客户端连接。
(6)接受连接:
使用 accept() 函数接受客户端的连接请求。当有客户端连接到服务器时,accept() 函数将返回一个新的套接字,该套接字用于与客户端进行通信。
(7)通信:
使用 send() 和 recv() 函数发送和接收数据。服务器和客户端都可以使用这些函数来发送和接收数据。
(8)关闭连接:
在通信结束后,使用 close() 函数关闭套接字,释放资源。
这些步骤提供了一个基本的框架来进行TCP编程。你可以根据需要进行适当的修改和扩展。同时还需要处理错误和异常情况,并确保适当地释放资源,以避免内存泄漏和其他问题。
服务器
(1)socket:创建一个用与链接的套接字(用于链接)
(2)bind:绑定自己的ip地址和端口
(3)listen:监听,将主动套接字转为被动套接字
(4)accept:阻塞等待客户端链接,链接成功返回一个用于通信套接字
(5)recv:接收消息
(6)send:发送消息
(7)close:关闭文件描述符
客户端
(1)socket:创建一个套接字
(2)填充结构体:填充服务器的ip和端口
(3)connect:阻塞等待链接服务器
(4)recv/send:接收/发送消息
(5)close:关闭
函数接口
1、socket
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain,int type,int protocol);
功能:创建套接字文件
参数:
domain:协议族 ,选择通信方式
AF_UNIX, AF_LOCAL 本地通信
AF_INET IPv4
AF_INET6 IPv6
type:通信协议-套接字类型
SOCK_STREAM 流式套接字
SOCK_DGRAM 数据报套接字
SOCK_RAW 原始套接字
protocol:协议 填0,自动匹配底层TCP或UDP等协议。根据type匹配系统默认自动帮助匹配对应协议
传输层:IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP
网络层:htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL)
返回值:成功。返回同于链接的文件描述符
失败 -1,更新errno
2、bind
```c
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd,const struct sockaddr* addr,socklen_t addrlen);
功能:绑定套接字 - ip和端口
功能:
sockfd:套接字文件描述符
addr:用于通信结构体 (提供的是通用结构体,需要根据选择通信方式,填充对应结构体-通信结构体由socket第一个参数确定)
addrlen:结构体大小
返回值: 成功0
失败:-1 更新errno
通用结构体:
struct sockaddr{
sa_family_t sa_family;
char sa_data[14];
}
ipv4的通信结构体:
struct sockaddr_in{
sa_family_t sin_family;/*AF_INET */
in_port_t sin_port;/* 端口 */
struct in_addr sin_addr;/* ip地址 */
};
struct in_addr{
uint32_t s_addr;
};
本地通信结构体:
struct sockaddr_un{
sa_family_t sun_family;/* AF_UNIX */
char sun_path[108];/* 套接字文件 */
};
3、listen
int listen(int sockfd,int backlog);
功能:监听,将主动套接字变为被动套接字
参数:
sockfd:套接字
backlog:同时响应客户端请求链接的最大个数,不能写0.
不同平台可同时链接的数不同,一般写6-8个
(队列1:保存正在连接)
(队列2,连接上的客户端)
返回值:成功 0 失败-1,更新errno
4、accept
int accept(int sockfd,struct sockaddr* addr,socklen_t* addrlen);
accept(sockfd,NULL,NULL);
阻塞函数,阻塞等待客户端的连接请求,如果有客户端连接,
则accept()函数返回,返回一个用于通信的套接字文件;
参数:
Sockfd :套接字
addr: 链接客户端的ip和端口号
如果不需要关心具体是哪一个客户端,那么可以填NULL;
addrlen:结构体的大小
如果不需要关心具体是哪一个客户端,那么可以填NULL;
返回值:
成功:文件描述符;//用于通信
失败:-1,更新errno
//监听套接字,将主动套接字转为被动套接字
if (listen(sockfd, 5) < 0)
{
perror("listern error.");
return -1;
}
//4.阻塞等待客户端链接,链接成功返回一个用于通信的文件描述符
acceptfd = accept(sockfd, NULL, NULL);
if (acceptfd < 0)
{
perror("accept error.");
return -1;
}
printf("acceptfd=%d
", acceptfd);
5、recv
ssize_t recv(int sockfd,void*buf, size_t len,int flags);
功能: 接收数据
参数:
sockfd: acceptfd ;
buf 存放位置
len 大小
flags 一般填0,相当于read()函数
MSG_DONTWAIT 非阻塞
返回值:
<0 失败出错 更新errno
==0 表示客户端退出
>0 成功接收的字节个数
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
//创建套接字
int sockfd;
int acceptfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("socket error.");
return -1;
}
printf("sockfd=%d
", sockfd);
//填充ipv4的通信结构体
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(8888);
serveraddr.sin_addr.s_addr = inet_addr("192.168.50.83");
//绑定套接字
if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("bind error.");
return -1;
}
printf("bind ok.
");
//3.监听套接字,将主动套接字转为被动套接字
if (listen(sockfd, 5) < 0)
{
perror("listern error.");
return -1;
}
//4.阻塞等待客户端链接,链接成功返回一个用于通信的文件描述符
acceptfd = accept(sockfd, NULL, NULL);
if (acceptfd < 0)
{
perror("accept error.");
return -1;
}
printf("acceptfd=%d
", acceptfd);
//5.循环接收消息
char buf[128];
int recvbyte;
while (1)
{
recvbyte = recv(acceptfd, buf, sizeof(buf), 0);
if (recvbyte < 0)
{
perror("recv error.");
return -1;
}
else if (recvbyte == 0)
{
printf("client exit.
");
break;
}
else
{
buf[recvbyte] = '