C语言--TCP/IP

什么是TCP/IP

是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成

IP转换函数

inet_addr()

将点分十进制数的 IP 地址转换成为网络字节序的 32 位二进制数值。

返回值:成功,返回 32 位二进制的网络字节序地址。不成功返回 0.

参数 cp:存放输入的点分十进制数 IP 地址字符串。

参数 inp:传出参数,保存网络字节序的 32 位二进制数值。

inet_aton()

将点分十进制数的 IP 地址转换成为网络字节序的 32 位二进制数值。

返回值:成功,则返 回 1,不成功返回 0.

参数 cp:存放输入的点分十进制数 IP 地址字符串。

参数 inp:传出参数,保存网络字节序的 32 位二进制数值。

inet_ntoa()

将网络字节序的 32 位二进制数值转换为点分十进制的 IP 地址。

端口号

一个是16位无符号整形,0-65535

区分一台主机接收到的数据包应该转交给哪个进程来进行处理

端口号转化

原因:网络中传输的数据必须按网络字节序,即大端字节序

主机 -----> 网络
uint16_t htons(uint16_t hostshort);

将一个无符号短整型的主机数值转换为网络字节顺序

网络 ------> 主机
uint16_t ntohs(uint16_t netshort);

将一个16位数由网络字节顺序转换为主机字节顺序。

地址名字转化

主机名或者域名 ------> IP地址
gethostbyname():

用于将域名(www.baidu.com)或主机名转换为 IP 址。

参数 hostname 指向存放域名或主机名的字符串。

IP地址 ------> 主机名或者域名
gethostbyaddr():

用于将 IP 地址转换为域名或主机名。

参数

addr 是一个 IP 地址,此时这个 ip 地址不是普通的字符串,而是要通过函数 inet_aton()转换。

len 为 IP 地址的长度, AF_INET 为 4。

family 可用 AF_INET:Ipv4 或 AF_INET6: Ipv6。

核心结构体

struct hostent {

                        char *h_name; /*正式主机名*/

                        char **h_aliases; /*主机别名*/

                        int h_addrtype; /*主机 IP 地址类型 IPv4 为 AF_INET*/

                        int h_length; /*主机 IP 地址字节长度,对于 IPv4 是 4 字节,即 32 位*/

                        char **h_addr_list; /*主机的 IP 地址*/ }

struct sockaddr_in {

                                short int sin_family; /*地址族*/

                                 unsigned short int sin_port; /*端口号*/

                                 struct in_addr sin_addr; /*IP 地址*/

                                unsigned char sin_zero[8]; /*未使用*/ };

 struct in_addr {

                         in_addr_t s_addr; /* 32 位 IPv4 地址,网络字节序 */ };

struct sockaddr {

                                //此结构体不常用

                                 unsigned short sa_family; /*地址族*/

                                 char sa_data[14]; /*14 节的协议地址,包含该 socket 的 IP 地址和端口号 */ };

TCP建立连接过程

服务器

1.创建监听套接字,用socket函数
int socket(int domain, int type, int protocol);
  • 参数

    • domain: 网域 AF_INET :IPv4 AF_INET6 :IPv6

    • type:选择传输协议 tcp /udp SOCK_STREAM ;tcp SOCK_DGRAM : udp

    • protocol: 基本废弃,一般赋0

  • 返回值

    • 成功返回描述网络套接字sockfd,失败返回-1

2.编写服务器地址信息
3.将服务器的地址信息与监听套接字绑定,用bind函数
int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);
  • 参数

    • sockfd 为前面 socket 的返回值

    • my_addr:封装ip地址和端口

    • addrlen:sockaddr 的结构体长度。 通常是计算 sizeof(struct sockadd);

  • 返回值

    • 成功则返回 0,失败返回-1

4.开始监听(设置允许的最大连接数),listen函数
int listen(int sockfd, int backlog);
  • 参数

    • sockfd 为前面 socket 的返回值.

    • backlog 指定同时能处理的最大连接要求,通常为 10 或者 5。 最大值可设至 128

  • 返回值

    • 成功则返回 0,失败返回-1

5.等待来自客户端的连接请求,accept函数
int accept(int sockfd, struct sockaddr *addr,socklen_t *addrlen);
  • 参数

    • sockfd 为前面 socket 的返回值.

    • addr:用于接受客户端的ip地址和端口号

    • addrlen:第二个参数大小

  • 返回值

    • 返回新的套接字描述符(通信套接字),专门用于与建立的客户端通信,失败-1

6.收发数据
ssize_t send(int s, const void *buf, size_t len, int flags);
  • 参数

    • s:新的套接字,即前面 accept 的返回值.

    • buf:要发送的数据缓冲区

    • len: 数据长度

    • flags: 一般赋0 .阻塞

  • 返回值

    • 成功返回真正发送的数据长度,失败-1

ssize_t recv(int s, void *buf, size_t len, int flags);
  • 参数

    • s:新的套接字,即为前面 accept 的返回值

    • buf:存放接收数据的缓冲区

    • len: 数据长度

    • flags: 一般赋0 .阻塞

  • 返回值

    • 成功返回真正接收的数据长度,失败-1

7.关闭套接字(网络连接)
close(sockfd)

客户端

1.创建通信套接字,用socket函数
2.编写服务器地址信息,即设置要连接的服务器的ip地址和端口等属性
3.连接服务器,用connect函数
int connect(int sockfd, const struct sockaddr*serv_addr, socklen_t addrlen);
  • 参数

    • sockfd 为前面 socket 的返回值

    • serv_addr 为结构体指针变量,存储着远程服务器的 IP 与端口号信息。

    • addrlen 表示结构体变量的长度

  • 返回值

    • 成功则返回 0,失败返回-1

4.收发数据,send和recv或者read和write
5.关闭通信套接字(网络连接)
close
/*server.c*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <time.h>
#define PORT 8888
#define IP "127.0.0.1"
int main(int argc, char *argv[])
{

	int sock_fd,clien_fd;
	struct sockaddr_in seraddr,clientaddr;
	socklen_t len;
	char buf[200] = "\0";
	//1.创建监听套接字
	sock_fd = socket(AF_INET,SOCK_STREAM,0);
	if(sock_fd < 0)
	{
		perror("socket error\n");
		return -1;
	}
	printf("创建监听套接字成功\n");
	memset(&seraddr,0,sizeof(seraddr));
	seraddr.sin_family = AF_INET;
	seraddr.sin_port = htons(PORT);
	seraddr.sin_addr.s_addr = inet_addr(IP);
	//inet_aton("192.168.15.2",&seraddr.sin_addr);//将点分式ip地址 转换为2进制
	//还可以用这个函数,直接将IP地址回写到seraddr结构体成员中的sin_addr
	//seraddr.sin_addr.s_addr = htonl(INADDR_ANY);  //IP号(htonl(INADDR_ANY)自动获取本机的IP号)
	//2.绑定
	if((bind(sock_fd,(struct sockaddr*)&seraddr, sizeof(seraddr))) < 0)
	{
		perror("bind error\n");
		exit(-1);
	}
	printf("绑定套接字成功\n");
	//3.监听
	if((listen(sock_fd,5)) < 0)
	{
		perror("listen error\n");
		exit(-1);
	}
	printf("监听成功........\n");
	len = sizeof(clientaddr);
		//4.连接
	if((clien_fd = accept(sock_fd,(struct sockaddr *)&clientaddr,&len)) < 0)
	{
		perror("accept error\n");
		exit(-1);
	}   
	printf("客户端连接成功\n");
	//5.发送接收
	while(1)
	{
		memset(buf,0,sizeof(buf));
		recv(clien_fd,buf,sizeof(buf),0);
		printf("RECV CLIENT %s : %s\n",inet_ntoa(clientaddr.sin_addr),buf);
		memset(buf,0,sizeof(buf));
		printf("please input >:");
		scanf("%s",buf);
		send(clien_fd,buf,sizeof(buf),0);
	}
	//6.关闭套接字
	close(clien_fd);
	close(sock_fd);
	return 0;
}

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define PORT 8888
#define IP "127.0.0.1"
int main(int argc, char *argv[])
{
	int sock_fd;
	struct sockaddr_in seraddr;
	socklen_t len;
	char buf[200] = "\0";
	sock_fd = socket(AF_INET,SOCK_STREAM,0);
	if(sock_fd < 0)
	{
		perror("socket error\n");
		exit(-1);
	}
	memset(&seraddr,0,sizeof(seraddr));
	seraddr.sin_family = AF_INET;
	seraddr.sin_port = htons(PORT);
	seraddr.sin_addr.s_addr = inet_addr(IP);
	if(connect(sock_fd,(struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)
	{
		perror("connet error\n");
		exit(-1);
	}
	printf("成功连接服务器\n");
	while(1)
	{
		printf("please input >:");
		scanf("%s",buf);
		send(sock_fd,buf,sizeof(buf),0);
		memset(buf,0,sizeof(buf));
		recv(sock_fd,buf,sizeof(buf),0);
		printf("RECV SERVER: %s\n",buf);
       }
		close(sock_fd);
		return 0;
}

  • 34
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于TCP/IP编程,以下是一个简单的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #define PORT 8888 int main() { int socket_fd, new_socket_fd; struct sockaddr_in server_addr, client_addr; socklen_t client_len; char buffer[1024] = {0}; char *message = "Hello from server"; // 创建 socket 文件描述符 if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 绑定本地地址和端口 server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(PORT); if (bind(socket_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 开始监听连接请求 if (listen(socket_fd, 1) < 0) { perror("listen failed"); exit(EXIT_FAILURE); } printf("Server is listening on port %d\n", PORT); while (1) { // 等待客户端连接 client_len = sizeof(client_addr); if ((new_socket_fd = accept(socket_fd, (struct sockaddr *)&client_addr, &client_len)) < 0) { perror("accept failed"); exit(EXIT_FAILURE); } // 发送欢迎消息给客户端 send(new_socket_fd, message, strlen(message), 0); printf("Hello message sent to client\n"); // 从客户端接收数据 read(new_socket_fd, buffer, 1024); printf("Receive message from client: %s\n", buffer); // 关闭当前的连接 close(new_socket_fd); } return 0; } ``` 这个程序会创建一个服务器的套接字,绑定到本地 IP 地址和指定的端口,随后开始监听连接请求。当客户端连接进来之后,服务器会向客户端发送一些欢迎信息,然后接收从客户端传来的消息,最后关闭连接。 这只是一个简单的示例程序,实际中需要根据业务逻辑进行适当的改进。希望这可以帮助你快速入门 TCP/IP 编程。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值