网络通讯(基于TCP/IP实现客户端/服务器的通讯)

王柳  金牌会员 | 2024-10-10 17:24:58 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 886|帖子 886|积分 2658

编程结构

被毗连者必要完成的任务(服务端):
1、创建socket内查对象,内核创建完成后会返回它的形貌符(该形貌只是为了完成毗连,三次握手)
2、准备本机地址(ip地址+端标语)
3、绑定(把本机地址与socket对象进行绑定)
4、开启监听,并设置排队的队列长度
5、等候毗连,毗连乐成后,内核会再返回一个毗连乐成的Socket形貌符,专门用来通讯
for(;;)
{
    6、接收哀求
    7、返回结果
}
8、关闭通讯的Socket对象
9、关闭毗连的Socket对象
毗连者必要完成的任务(客户端):
1、创建socket内查对象,内核创建完成后会返回它的形貌符
2、准备被毗连者的地址(ip地址+端标语)
3、发起毗连,使用Socket+地址(ip地址+端标语)发起毗连哀求
for(;;)
{
    4、发送哀求
    5、接收结果
}
6、关闭Socket对象

相关函数

int socket(int domain, int type, int protocol);
功能:创建Socket对象
domain:
    AF_UNIX, AF_LOCAL   采用本地socket文件进行通讯,假如用它则只能本机上的两个历程进行通讯
    AF_INET             IPv4地址
    AF_INET6               IPv6地址
type:
    SOCK_STREAM    数据流    TCP
    SOCK_DGRAM 报文 UDP
protocol:
    特殊通讯协议,写0即可
返回值:
    乐成则返回Socket对象形貌符,失败返回-1。
// 根本地址类型,它是socket系列接口的外貌参数,而实际使用的是sockaddr_un或sockaddr_in,我们必要把sockaddr_in逼迫转换成sockaddr类型。
struct sockaddr_in 
{
    sa_family_t sin_family;        // 地址类型,与domain保持同等即可
    in_port_t sin_port;            // 端标语,网络字节序的2字节整数
    struct in_addr sin_addr.s_addr;    // IP地址,网络字节序的4字节整数
};
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:绑定Socket对象与通讯地址
sockfd:Socket对象形貌符
addr:通讯地址,实际提供可能是sockaddr_un或sockaddr_in,必要对它们进行逼迫转换
addrlen:addr结构体的字节数
返回值:乐成返回0,失败返回-1
    
int listen(int sockfd, int backlog);
功能:开启Socket对象的监听
sockfd:Socket地址形貌符
backlog:备胎的数目
    
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:等候毗连,没有乐成毗连之前,会进入阻塞状态
sockfd:Socket对象形貌符
addr:用于存储毗连者的通讯地址
addrlen:
    既是输入(告诉accetp接口,addr结构体的字节数),也是输出(实际接收到的addr结构的字节数)
返回值:建立毗连的,能够通讯的Socket对象形貌符,失败返回-1
    
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:让sockfd对象向addr地址发起毗连
sockfd:Socket对象形貌符
addr:毗连目标的地址
addrlen:addr结构体的字节数
返回值:乐成返回0,失败返回-1
    
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:从Socket对象读接收干字节
sockfd:Socket对象形貌符
buf:接收数据的内存块首地址
len:buf的字节数
flags:是否阻塞,写0即可
返回值:乐成接收到了多少个字节,失败返回-1
    
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:通过Socket对象发送多少字节
sockfd:Socket对象形貌符
buf:要发送的内存块首地址
len:要发送的字节数
flags:是否阻塞,写0即可
返回值:乐成发送了多少个字节,失败返回-1
    
int close(int fd);
功能:关闭fd形貌所代表的内查对象
    
uint16_t htons(uint16_t hostshort);
功能:把本地字节序的 unsigned short 类型的数据转换网络字节序
    
in_addr_t inet_addr(const char *cp);
功能:把字符串格式 点分十进制的ip地址 转换成网络字节序的4字节ip地址

代码:

服务端:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. int main(int argc,const char* argv[])
  9. {
  10.         // 创建socket对象
  11.         int server_fd = socket(AF_INET,SOCK_STREAM,0);
  12.         if(0 > server_fd)
  13.         {
  14.                 perror("socket");
  15.                 return -1;
  16.         }
  17.         // 准备本机地址
  18.         struct sockaddr_in addr;
  19.         addr.sin_family = AF_INET;
  20.         addr.sin_port = htons(2233);
  21.         addr.sin_addr.s_addr = inet_addr("10.0.2.15");
  22.         socklen_t addrlen = sizeof(addr);
  23.         // 绑定socket对象和地址       
  24.         if(bind(server_fd,(struct sockaddr*)&addr,addrlen))
  25.         {
  26.                 perror("bind");
  27.                 return -2;
  28.         }
  29.         // 开启监听
  30.         if(listen(server_fd,6))
  31.         {
  32.                 perror("listen");
  33.                 return -3;
  34.         }
  35.         // 等待连接
  36.         int sockfd = accept(server_fd,(struct sockaddr*)&addr,&addrlen);
  37.         if(0 > sockfd)
  38.         {
  39.                 perror("accept");
  40.                 return -4;
  41.         }
  42.         char buf[BUFSIZ];
  43.         for(;;)
  44.         {
  45.                 // 接收数据
  46.                 int ret = read(sockfd,buf,BUFSIZ);
  47.                 if(0 >= ret || !strcmp("quit",buf))
  48.                         break;
  49.                 printf("recv:%s byte:%d\n",buf,ret);
  50.                 strcat(buf,",return!");
  51.                 // 返回数据
  52.                 ret = write(sockfd,buf,strlen(buf)+1);
  53.                 if(0 >= ret)
  54.                         break;
  55.         }
  56.        
  57.         printf("通信结束!\n");
  58.         // 关闭负责通信的socket对象
  59.         close(sockfd);
  60.         // 关闭负责连接的socket对象
  61.         close(server_fd);
  62.         return 0;
  63. }
复制代码
客户端:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. int main(int argc,const char* argv[])
  9. {
  10.         // 创建socket对象
  11.         int sockfd = socket(AF_INET,SOCK_STREAM,0);
  12.         if(0 > sockfd)
  13.         {
  14.                 perror("socket");
  15.                 return -1;
  16.         }
  17.         // 准备服务端的地址
  18.         struct sockaddr_in addr;
  19.         addr.sin_family = AF_INET;
  20.         addr.sin_port = htons(2233);
  21.         addr.sin_addr.s_addr = inet_addr("10.0.2.15");
  22.         socklen_t addrlen = sizeof(addr);
  23.         // 连接
  24.         if(connect(sockfd,(struct sockaddr*)&addr,addrlen))
  25.         {
  26.                 perror("connect");
  27.                 return -2;
  28.         }
  29.         char buf[BUFSIZ];
  30.         for(;;)
  31.         {
  32.                 printf(">>>");
  33.                 scanf("%s",buf);
  34.                 // 发送数据
  35.                 int ret = write(sockfd,buf,strlen(buf)+1);
  36.                 if(0 >= ret || !strcmp("quit",buf))
  37.                         break;
  38.                 // 接收数据
  39.                 ret = read(sockfd,buf,BUFSIZ);
  40.                 if(0 >= ret)
  41.                         break;
  42.                 printf("recv:%s byte:%d\n",buf,ret);
  43.         }       
  44.         printf("通信结束!\n");
  45.         // 关闭socket对象
  46.         close(sockfd);
  47.        
  48.         return 0;
  49. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王柳

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表