【通信方式五】socket编程之TCP通信

1、网络字节序

网络字节序就是熟知的关于大小端的问题,关于前面的大小端的判断方法,以及代码实现再此就不在赘述,下面只谈网络中的字节序问题

(如何判定当前机器的大小端:http://blog.csdn.net/double_happiness/article/details/71480861

发送方主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络中接收到的字节依次保存在接受缓冲区中,也是暗中内存从低地址到高地址的顺序进行保存,因此网络数据流的地址是这样规定的:先发出的数据是低地址,后发出的是高地址,即网络数据采取大端字节序。

Linux下的网络字节序和主机字节序的转换

#include<arpa/inet.h>

unit32_t htonl(uint32_t hostlong);
unit16_t htonl(uint16_t netshort);
unit32_t ntohl(uint32_t netlong);
unit16_t ntohl(uint16_t netshort);
其中hton系列的都是主机序列转为网络序列,ntoh的都是网络序列转化为主机序列。

2、socket地址的数据类型及相关函数

socketaddr数据结构


从上面数据结构的设计,不管对应的是IPv4、IPv6还是UNIX,只要取得这种socket结构体的首地址,而不需要知道具体是那种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容,因此socket API可以接受各种类型的sockaddr结构体指针做参数,底层直接使用void*类型以便接受各种类型的指针,因此这些函数的参数都用struct socketaddr*类型表示,在传递参数时需要进行强制类型转化。

(1)字符串转in_addr函数

#include <arpa/inet.h>

int inet_aton(const char* str,struct in_addr *addr);
in_addr_t inet_addr(const char* str);
int inet_pton(int family,const char* str,void* addr);
(2)in_addr转字符串的函数

char* inet_ntoa(struct in_addr inaddr);
const char* inet_ntop(int family,const void* addr,char* str,size_t len);
3、TCP通信流程

服务器端通过调用socket(),bind(),listen()创建监听套接字,然后通过accept()从网络中能不断的监听获取新的连接,完成对应的数据传输。服务器端分别模拟单进程,多进程,多线程的情况。

客户端只需要要创建套接字,然后调用connect连接到服务器端完成数据的传输任务即可。

相关函数

(1)socket函数——创建socket套接字

#include <sys/types.h>        
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

参数说明:

domain:The  domain argument specifies a communication domain; this selects the protocol family which will be used for communication.

Name               	 Purpose                          Man page
AF_UNIX, AF_LOCAL   Local communication             	   unix(7)
AF_INET             IPv4 Internet protocols        	   ip(7)
AF_INET6            IPv6 Internet protocols       	   ipv6(7)
AF_IPX              IPX - Novell protocols
AF_NETLINK          Kernel user interface device  	   netlink(7)
AF_X25              ITU-T X.25 / ISO-8208 protocol 	    x25(7)
AF_AX25             Amateur radio AX.25 protocol
AF_ATMPVC           Access to raw ATM PVCs
AF_APPLETALK        Appletalk                       	   ddp(7)
AF_PACKET           Low level packet interface     	   packet(7)

type: 


protocol:默认缺省为0

返回值:创建成功返回新创建的socket的文件描述符,创建失败返回-1;

(2)bind函数

#include <sys/types.h>         
#include <sys/socket.h>

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

参数说明:

socket:socket的成功返回值

addr:struct sockaddr结构体指针变量,该结构体图已经在上面给出

addrlen:addr的有效长度

返回值:成功返回0失败返回-1

(3)listen函数

#include <sys/types.h>     
#include <sys/socket.h>

int listen(int sockfd, int backlog);

参数说明:

socket:socket函数的成功返回值

backlog:是一个整数,一般不能给太大

返回值:成功返回0失败返回-1

(4)accept函数

#include <sys/types.h>         
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数说明:

sockfd:socket函数的成功范湖值

addr:struct sockaddr结构体指针变量(客户端的IP和port)

addrlen:addr的有效长度

返回值:成功返回0失败返回-1

(5)connect函数

#include <sys/types.h>          
#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

参数说明:

sockfd:socket函数的成功范湖值

addr:struct sockaddr结构体指针变量(服务器端的IP和port)

addrlen:addr的有效长度

返回值:成功返回0失败返回-1



代码实现

客户端的实现都是不变的,对应的只需要修改服务器端相应的代码即可,由于多进程的程序需要多台主机再此就不给出演示,只给出相关代码

单进程server.c


客户端client.c




运行演示



多进程代码实现





多线程版本代码实现





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

double_happiness

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值