LINUX下 简易TCP多线程编程api

目录

什么是TCP--

TCP多线程编程服务器模型

TCP多线程编程客户端模型

编程实现TCP


1)什么是TCP

TCP是一种面向连接的传输层协议,他能提供可靠性的通信。即数据无误,数据无丢失,数据无重复到达,数据无失序的通信。

适用于对传输质量要求高,以及传输大量数据的通信。能够确保在传输大量数据的时候保证通信的可靠性。在一些通讯软件的登录账号管理一类的功能也通常使用TCP协议。

2)TCP编程服务器模型

socket函数创建套接字文件,返回套接字文件描述符,用于监听客户连接。

bind函数用于绑定套接字文件,ip地址和port端口号,将这些绑定在一起建立固定对应的关系。 

listen 函数用于被动监听客户端的连接,将套接字描述符变为被动描述符。

accept 用于被动监听客户的握手请求,三次握手完成后会返回一个新的套接字描述符用于通信。

send 向client发送信息

recv 接受client返回的信息

close 关闭,四次握手后断开连接。

3)TCP编程客户端模型

4)头文件

这些是在简单的tcp多线程编程中会用到的头文件,都放在了net.h里。

创建一个头文件看起来会更舒服一点。

5)编程实现TCP多线程服务器

socket的第一个参数是int domain,在man手册里。

AF_INET为IPv4 网络协议的套接字模型,而AF_INET6为IPv6的,在本次编程中均使用AF_INET。第二个参数为类型 type,

SOCK_STREAM是基于TCP的,数据传输比较有保障。SOCK_DGRAM是基于UDP的,专门用于局域网,基于广播SOCK_STREAM 是数据流,一般是tcp/ip协议的编程,SOCK_DGRAM分是数据抱,是udp协议网络编程,显然在TCP编程中会选择 SOCK_STREAM。

第三个参数因为通常只有一种特殊连接,所以多设置为0。

socket函数的返回值,成功时返回文件描述符,失败时返回-1。

绑定失败的时候使用perror打印错误信息,

bind函数,在使用的时候要建立一个结构体。在man手册中有标准结构体,但我们通常会使用另一个结构体,struct sockaddr_in这个结构体。

在填写struct sockaddr_in的时候,其中还有 sin_zero占用字节,所以要进行结构体的初始化清零,可以使用bzero函数。

使用atoi函数将字符串转换为整形数。在填写结构体sin.sin_port的时候要注意使用htons将主机字节序转换为网络字节序。

htonl 表示 host to network long ,用于将主机 unsigned int 型数据转换成网络字节顺序;
htons 表示 host to network short ,用于将主机 unsigned short 型数据转换成网络字节顺序;

使用inet_pton填写ip的时候要注意(void *)的类型强制转换。

在bind的绑定的时候要注意我们填写的结构体是struct sockaddr_in 而bind需要的是标准结构体,要进行类型转换。

接着写完listen函数后,可以进行线程的创建。因为accept函数会返回一个新的套接字文件描述符,所以定义一个新的int类型变量去接受他的返回值,int acceptfd。在创建线程的时候.

第一个参数是一个指针,我们可以定义一个pthread_t类型的变量每一个变量都可以表示一个进程,然后传地址进去。

同时还要再创建一个结构体struct sockaddr_in cin用于接受客户端数据。

写一个while循环来accept不同客户端的。在后续结果反馈中想要得到client的地址信息的话,还需要一个inet_ntop的函数,来转换成我们熟悉的十进制ip。

pthread_create函数中第二个参数,const pthread_attr_t *attr,用于手动设置线程的一些属性,大部分时间都不需要我们再去进行更改,可以填写NULL。

第三个参数void *(*start_routine) (void *),函数指针的方式指明新建线程需要执行的函数,该函数的参数最多有 1 个(可以省略不写),形参和返回值的类型都必须为 void* 类型。void* 类型又称空指针类型,表明指针所指数据的类型是未知的。使用此类型指针时,我们通常需要先对其进行强制类型转换,然后才能正常访问指针指向的数据。我们可以定义一个函数用来完成对客户端的接受数据和传送数据。

第四个参数 void *arg:指定传递给 start_routine 函数的实参,当不需要传递任何数据时,将 arg 赋值为 NULL 即可。但我们因为要接受和传输数据,所以要将acceptfd取地址当做实参。

在while循环外要加上close(fd),接下来用不到fd了要及时关闭。

在clientdata_handle(void *arg)函数中,因为形参我们必须要使用void *型,所以在函数里再定义一个int 类型的acceptfd。

取出来我们所需要的传进来的数据。

接着我们要定义一个char类型的数组用于接收客户端数据和向客户端发送数据。

接下来用while循环来接收和发送数据,在while循环中还是要记得使用bzero对buf进行初始化。

当recv的返回值为0的时候说明connect关闭。可以直接退出。当客户端想退出的时候可以输入quit,我们可以用一个简单的strncasecmp的函数进行字符串比较。

6)客户端的编程实现

在简单的tcp编程api中完成了服务器的编程,那么客户端将会很简单,增加一个connect函数即可。

其余几乎一模一样。

还可以对服务器做一点小优化。

这时候当输入不规范的时候就会有提示:

7)运行结果

在不同终端中输入ip和port即可,因为是多线程的服务器,还可以实现同时对不同客户端的接收服务。

发送一个love you吧

就可以接收到数据啦。

当然,想退出的话就输入quit就可以退出了。

学习完网络编程也过了一个多月了,主要是也帮助自己回忆一下TCP的简单编程,便于后续的继续学习。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值