文章目录

  • 1.创建socket
    • domain
    • type
    • protocol
    • errno
  • 2.命名socket
    • sockaddr_in
    • bind
    • connect()
  • 3.监听socket
  • 4.接收连接
  • 5.发起连接(暂时了解)
  • 6.关闭连接
    • close()
    • showdown()
    • 7.TCP数据读写
  • 8.UDP数据读写(了解)
  • 9.实现多线程TCP服务器

在网络编程中客户端和服务端所需要的函数如下图:

1.创建socket

#include<sys/types.h>
#include<sys/socket.h>
int socket(int domain, int type, int protocol);

这个函数建立一个协议族为domain、协议类型为type、协议编号为protocol的套接字文件描述符。如果函数调用成功,会返回一个标识这个套接字的文件描述符,失败的时候返回-1。

domain

函数socket()的参数domain用于设置网络通信的域,函数socket()根据这个参数选择通信协议的族。通信协议族在文件sys/socket.h中定义。

如下,domain的值及含义

type

函数socket()的参数type用于设置套接字通信的类型,主要有SOCKET_STREAM(流式套接字)、SOCK——DGRAM(数据包套接字)等。

如下type的值及含义


并不是所有的协议族都实现了这些协议类型,例如,AF_INET协议族就没有实现SOCK_SEQPACKET协议类型。

protocol

函数socket()的第3个参数protocol用于制定某个协议的特定类型,即type类型中的某个类型。通常某协议中只有一种特定类型,这样protocol参数仅能设置为0;但是有些协议有多种特定的类型,就需要设置这个参数来选择特定的类型。

类型为SOCK_STREAM的套接字表示一个双向的字节流,与管道类似。流式的套接字在进行数据收发之前必须已经连接,连接使用connect()函数进行。一旦连接,可以使用read()或者write()函数进行数据的传输。流式通信方式保证数据不会丢失或者重复接收,当数据在一段时间内任然没有接受完毕,可以将这个连接人为已经死掉。
SOCK_DGRAM和SOCK_RAW 这个两种套接字可以使用函数sendto()来发送数据,使用recvfrom()函数接受数据,recvfrom()接受来自制定IP地址的发送方的数据。
SOCK_PACKET是一种专用的数据包,它直接从设备驱动接受数据。

errno

函数socket()并不总是执行成功,有可能会出现错误,错误的产生有多种原因,可以通过errno获得:

如下 errno的值及含义


示例,建立一个流式套接字:

int sock = socket(AF_INET, SOCK_STREAM, 0);

2.命名socket

socket() 函数用来创建套接字,确定套接字的各种属性,然后服务器端要用 bind() 函数将套接字与特定的IP地址和端口绑定起来,只有这样,流经该IP地址和端口的数据才能交给套接字处理;而客户端要用 connect() 函数建立连接。

sockaddr_in

这个结构体用来处理网络通信的地址。

bind

int bind(int sock, struct sockaddr *addr, socklen_t addrlen);

-sock:文件描述符
-addr:sockaddr结构体变量的指针
-addrlen:addr变量的大小,可用sizeof()计算

返回值:

代码演示:
将创建的套接字与IP地址127.0.0.1、端口8888绑定。

//创建套接字
int serv_sock = socket(AF_INET, SOCK_STREAM, 0);
//创建sockaddr_in结构体变量
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
serv_addr.sin_family = AF_INET;  //使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
serv_addr.sin_port = htons(8888);  //端口
//将套接字和IP、端口绑定
bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

-inet_addr 将字符串形式的IP地址 -> 网络字节顺序 的整型值
-inet_ntoa 网络字节顺序的整型值 ->字符串形式的IP地址
-网络字节顺序与本地字节顺序之间的转换函数:
htonl()–“Host to Network Long”
ntohl()–“Network to Host Long”
htons()–“Host to Network Short”
ntohs()–“Network to Host Short”

connect()

int connect(int sock, struct sockaddr *serv_addr, socklen_t addrlen);

3.监听socket

socket被命名之后还不能马上接受客户的连接,需要创建一个监听队列存放待处理的客户连接。

#include <sys/socket.h>
int listen(int sockfd, int backlog);

-sockfd:指定被监听的socket
-backlog:提示内核监听队列的最大长度。监听队列的长度如果超过backlog,服务器将不受理新的客户端连接,客户端也将收到ECONNREFUSED错误信息。
返回值:成功返回0,失败返回-1

请求队列:当套接字正在处理客户端请求时,如果有新的请求进来,套接字是没法处理的,只能把它放进缓冲区,待当前请求处理完毕后,再从缓冲区中读取出来处理。如果不断有新的请求进来,它们就按照先后顺序在缓冲区中排队,直到缓冲区满。这个缓冲区,就称为请求队列(Request Queue)。

4.接收连接

#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd,struct sockaddr *addr, socklen *addrlen);

-sockfd:执行过listen系统调用的监听socket
-addr:获取被接受连接的远端socket地址
-返回值:失败返回-1

accpet()成功时返回一个新的连接socket,该socket唯一的表示了被接受的这个连接,服务器可通过读写该socket来与被接受连接对应的客户端通信。

5.发起连接(暂时了解)

客户端通过connect调用主动的与服务器建立连接。

#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen);

6.关闭连接

close()

#include <unistd.h>
int close(int fd);

-fd:待关闭的socket的描述符

将fd的引用计数减一只有当引用计数为0的时候才真正的关闭连接。一次fock将是的父进程当中打开的socket引用计数加一。因此必须都关闭才会真正的将连接关闭。

showdown()

调用立即终止连接。

7.TCP数据读写

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd,void *buf,size_t len,int flags);
ssize_t send(int sockfd,const void *buf,size_t len,int flags);


8.UDP数据读写(了解)

9.实现多线程TCP服务器

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<string.h>
#include<pthread.h>void* thread_start(void* arg){int client = *(int*)arg;//保存接收到的数据char buf[1024] = { 0 };for (;;){int recvlen = recv(client, buf, sizeof(buf)-1, 0);if (recvlen <= 0)break;buf[recvlen] = '\0';if (strstr(buf, "quit") != NULL){char re[] = "quit success!\n";send(client, re, strlen(re) + 1, 0);break;}int sendlen = send(client, "ok\n", 4, 0);printf("recv %s\n", buf);}close(client);
}int main(int argc, char* argv[]){//创建socketint sock = socket(AF_INET, SOCK_STREAM, 0);if (sock == -1){printf("create socket failed!\n");return -1;}//绑定一个端口unsigned short port = 9999;if (argc > 1){port = atoi(argv[1]);//将字符串转换为一个整数}sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(port);//将主机字节顺序转换为网络字节顺序【默认大端】(处理大端小端问题)saddr.sin_addr.s_addr = htonl(0);if (bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0){printf("bind port %d failed!\n", saddr.sin_port);return -2;}printf("bind port %d success!\n", port);listen(sock, 10);//在一段时间内最大可以让多少个链接进来for (;;){//接受客户端请求sockaddr_in caddr;socklen_t len = sizeof(caddr);//int client=accept(sock, 0, 0);int client = accept(sock, (sockaddr*)&caddr, &len);if (client <= 0)break;printf("accept client %d \n", client);char* ip = inet_ntoa(caddr.sin_addr);unsigned short cport = ntohs(caddr.sin_port);printf("client ip is %s,port is %d\n", ip, cport);//创建线程pthread_t tid;pthread_create(&tid, NULL, thread_start, (void*)&client);//将主线程与子线程分离,子线程执行完毕后自动释放资源pthread_detach(tid);}close(sock);return 0;
}

Socket中接口函数简介相关推荐

  1. python中set()函数的用法,python中set()函数简介及实例解析

    python中set()函数简介及实例解析 set函数也是python内置函数的其中一个,属于比较基础的函数.其具体介绍和使用方法,下面进行介绍. set() 函数创建一个无序不重复元素集,可进行关系 ...

  2. python中set函数_python中set()函数简介及实例解析

    set函数也是python内置函数的其中一个,属于比较基础的函数.其具体介绍和使用方法,下面进行介绍. set() 函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集.差集.并 ...

  3. C#中Math函数简介

    C#中Math函数简介 Math.abs() 计算绝对值 Math.acos() 计算反余弦值 Math.asin() 计算反正弦值 Math.atan() 计算反正切值 Math.atan2() 计 ...

  4. SQL中decode()函数简介

    SQL中decode()函数简介 Select decode(columnname,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值)From talbenameWhere - 其中:co ...

  5. SQL中 decode()函数简介

    今天看别人的SQL时看这里面还有decode()函数,以前从来没接触到,上网查了一下,还挺好用的一个函数,写下来希望对朋友们有帮助哈! decode()函数简介: 主要作用:将查询结果翻译成其他值(即 ...

  6. oracle sql文字列函数,Oracle 数据库SQL中 decode()函数简介

    decode()函数简介: 主要作用:将查询结果翻译成其他值(即以其他形式表现出来,以下举例说明): 使用方法: Select decode(columnname,值1,翻译值1,值2,翻译值2,.. ...

  7. Socket中send()函数和rece()函数详解

    1.send函数 int send (SOCKET s, const char FAR *buf. int len,int flags); 不论是客户还是服务器应用程序都是用send函数来向TCP连接 ...

  8. oracle mysql substr_Oracle数据库中substr()函数简介说明

    摘要: 下文讲述Oracle数据库中substr函数应用简介,如下所示: oracle substr函数功能说明 substr函数功能: substr函数在oracle数据库中的功能为:字符串截取函数 ...

  9. Socket中send()函数和recv()函数详解

    目录 1.send函数 2.recv函数 关于socket的send和recv的超时设置 1.send函数 int send( SOCKET s, const char FAR *buf, int l ...

最新文章

  1. python饼图怎么显示中文_python生成饼图解决中文乱码
  2. JavaScript 四. Math对象的属性和方法
  3. 牛客网暑期ACM多校训练营(第五场)A-gap (二分答案)
  4. ITK:使用二进制阈值对图像阈值
  5. sap 发送mesage_SAP的message机制
  6. struts2+jquery 实现ajax登陆
  7. 一个简单的 iBatis 实现——完整示例
  8. 多线程socket 端口扫描程序,实现了,但是速度不行,求指点。
  9. [jQuery]使用jQuery.Validate进行客户端验证(初级篇)——不使用微软验证控件的理由...
  10. 微信小程序登陆注册功能实现
  11. C语言实训心得体会(精选4篇)
  12. HL340(usb转串口线)驱动
  13. python PIL 图像增强
  14. How long have you been studying English(第一节)
  15. mac 文档 只读修改
  16. Linux LCD 驱动调色板原理
  17. Springboot美妆网站的设计与实现毕业设计-附源码211539
  18. android 模拟自动点击,自动点击模拟器app
  19. 垂直居中对齐四种样式
  20. pwm占空比的c语言编程详解,盘点占空比、PWM、GPIO三者含义及原理分析

热门文章

  1. 凯勒姆机器人系统_苏州凯勒姆机器人系统工程有限公司
  2. 老男孩python全栈开发视频教程_老男孩Python全栈开发(92天全)视频教程 自学笔记05...
  3. 华为手机怎么识别提取图片文字?APP一键识别
  4. 2021-4-21二分搜索
  5. CAD二次开发命令窗口交互(COM接口c#语言)
  6. 客户售后服务工作单管理系统 下载
  7. Windows11 任务管理器的几种打开方式
  8. 雷蛇Ubuntu 无线网卡外接配置
  9. 四川大学计算机跨专业考研,四川大学计算机好考研吗?四川大学考研874专业怎么复习?...
  10. 通过示教器或ROS控制UR机械臂