socket编程基础知识

本文介绍了socket编程的基础知识,包括IP地址、端口号和套接字的概念,以及网络字节序的处理。讲解了字节序转换函数、IP地址转换和网络套接字函数的使用,如socket、bind、listen、accept、connect等。还概述了socket模型创建流程及编程实例,涉及服务器和客户端的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概念
  IP地址:在网络环境中唯一标识一台主机。
  端口号(port):在主机中唯一标识一个进程。
  socket:就是所谓的套接字,在Linux中socket是一种伪文件(不占用内存),用一个文件描述符指代。
  网络字节序:
    大端序:低地址存高位,TCP/IP协议规定网络数据流应采用大端字节序。
    小端序:低地址存低位,计算中存储数据常用的格式。

二、常用函数
  字节序转换函数:
    uint32_t htonl(uint32_t hostlong)
    uint16_t htons(uint16_t hostshort)
    uint32_t ntohl(uint32_t netlong)
    uint16_t ntohs(uint16_t netshort)
    h代表host(主机),n代表network,l表示32位长整数(IP地址),s表示16位短整数(端口号)
  IP地址转换:
    点分十进制字符串 ——> uint32_t ——> htonl() ——> 网络字节序
    点分十进制字符串 ——> inet_pton() ——> 网络字节序
    网络字节序 ——> inet_ntop() ——> 点分十进制字符串
  网络套接字函数
    创建套接字,成功返回套接字描述符,失败返回-1
    int socket (int __domain, int __type, int __protocol)

    绑定套接字
    int bind (int __fd, const struct sockaddr *, socklen_t __len)

    开始接收套接字上的连接,成功返回0,失败返回-1,并设置errno
    int listen (int __fd, int __n)

    接受客户端连接请求,如果没有则阻塞等待,成功返回0,失败返回-1,并设置errno
    int accept (int __fd, struct sockaddr *__restrict, socklen_t *__restrict __addr_len)

    向对端发起连接请求,成功返回0,失败返回-1,并设置errno
    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)

    对套接字的引用计数减1,当套接字的引用计数为0时,关闭套接字,并回收释放套接字所占资源
    int close (int __fd)

    不管套接字的引用计数为多少,直接关闭套接字的读端或者写端或者全部,但是并不回收释放套接字所占用资源
    int shutdown(int sockfd, int how)
    how参数可为:SHUT_RD、SHUT_WR、SHUT_RDWR

    将套接字设置为非阻塞
    fcntl(fd, F_SETFL, O_NONBLOCK)

    设置可重用套接字所绑定的地址以及端口号
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &op, sizeof(op))

    读写函数
    ssize_t read(int fd, void *buf, size_t nbytes)
    ssize_t write(int fd, const void *buf, size_t count)
    ssize_t recv (int __fd, void *__buf, size_t __n, int __flags)
    ssize_t send (int __fd, __const void *__buf, size_t __n, int __flags)

三、socket模型创建流程图
在这里插入图片描述
四、编程例子(为了突出逻辑性,所以没有返回值检查)
服务器:

		#include<iostream>
		#include<unistd.h>
		#include<sys/socket.h>
		#include<arpa/inet.h>
		#include<cctype>
		
		#define SERV_IP "192.168.200.131"	//服务器IP
		#define SERV_PORT 6666				//服务器端口
		
		int main() {
			//-------创建套接字-------
			int sfd = socket(AF_INET, SOCK_STREAM, 0);
		
			//-------绑定套接字-------
			sockaddr_in servaddr;	//套接字信息存储
			servaddr.sin_family = AF_INET;
			servaddr.sin_port = htons(SERV_PORT);					//端口值转换成网络字节序
			inet_pton(AF_INET, SERV_IP, &servaddr.sin_addr);	//IP地址转换成网络字节序
			bind(sfd, (sockaddr *)&servaddr, sizeof(servaddr));	//绑定套接字
		
			//-------设置最大待连接请求-------
			listen(sfd, 128);
		
			//-------阻塞等待连接,当有连接请求时接收连接--------
			sockaddr_in clieaddr;
			socklen_t clieaddr_struct_size;
			int cfd = accept(sfd, (sockaddr *)&clieaddr, &clieaddr_struct_size);
		
			//-------处理客户端请求-------
			char buf[4096];
			ssize_t readlen = 0;	//从客户端读到的数据的长度
			while (1) {
				readlen = read(cfd, buf, sizeof(buf));
				if (readlen == 0) break;
		
				//执行客户端请求——小写转大写
				for (int i = 0; i < readlen; ++i)
					buf[i] = toupper(buf[i]);
		
				write(cfd, buf, readlen);	//将请求结果写回客户端
			}
		
			close(cfd);
			close(sfd);
		
		
			return 0;
		}

客户端

		#include<iostream>
		#include<unistd.h>
		#include<sys/socket.h>
		#include<arpa/inet.h>
		#include<cstring>
		#include<cstdio>
		
		#define SERV_IP "192.168.200.131"
		#define SERV_PORT 6666
		
		int main() {
			//-------创建套接字--------
			int cfd = socket(AF_INET, SOCK_STREAM, 0);
		
			//-------绑定套接字(客户端可以不执行该操作,因为操作系统会隐式绑定)--------
		
			//-------请求连接服务器--------
			sockaddr_in servaddr;	//编写服务器的IP地址与端口号
			servaddr.sin_family = AF_INET;
			servaddr.sin_port = htons(SERV_PORT);
			inet_pton(AF_INET, SERV_IP, &servaddr.sin_addr);
			connect(cfd, (sockaddr *)&servaddr, sizeof(servaddr));
		
			//-------请求服务器---------
			char buf[4096];
			ssize_t readlen = 0;	//服务器回写的内容长度
			ssize_t writelen = 0;	//写给服务器的数据长度
			while (1) {
				std::cin.getline(buf, sizeof(buf));
				writelen = write(cfd, buf, strlen(buf));
				if (writelen == 0) break;
				readlen = read(cfd, buf, sizeof(buf));
				for (int i = 0; i < readlen; ++i)
					std::cout << buf[i];
				std::cout << std::endl;
			}
		
			close(cfd);
		
			return 0;
		}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值