服务器搭建(TCP套接字)-基础版(客户端)

一、socket

1.1、vim man查看socket

cpp 复制代码
:!man socket


1.2、 依赖的头文件

cpp 复制代码
 #include <sys/types.h>     
 #include <sys/socket.h>

1.3、原型

cpp 复制代码
int socket(int domain, int type, int protocol);
domain 说明
AF_INET IPV4协议
AF_INET6 IPV6协议
AF_LOCAL Unix域协议
type 说明
SOCK_STREAM 字节流套接字(TCP/SCTP)
SOCK_DGRAM 数据报套接字(UDP)
SOCK_RAM 原始套接字 (IPv4/IPv6)
SOCK_SEQPACKET 有序分组套接字(SCTP)
protocol 说明
IPPROTO_CP TCP传输协议
IPPROTO_UDP UDP传输协议
IPPROTO_SCTP SCTP传输协议

socket函数在成功时会返回一个小的非负整数值 ,它与文件描述符类似,就称它为套接字描述符。只需要指定协议族(IPV4、IPV6或Unix)和套接字类型即可

  • 代码实现
cpp 复制代码
socket_fd=socket(AF_INET,SOCK_STREAM,0);

二、connect

2.1、原型

cpp 复制代码
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

connect() 函数用于在客户端应用程序中与服务器建立连接。需要注意的是,connect() 函数可能会阻塞,直到连接成功建立或发生错误。因此,您可以使用适当的超时机制或非阻塞 Socket 设置来控制连接过程的行为。

入参:

  • sockfd:要连接的客户端 Socket 的文件描述符。
  • addr:指向服务器地址结构的指针,其中包含服务器的 IP 地址和端口号。
  • addrlen:服务器地址结构的长度。

返回值:

  • 0 表示连接成功
  • 返回值为 -1 表示连接失败,并设置相应的错误代码(可以使用 perror() 函数打印错误信息)。

2.2、代码

cpp 复制代码
#define SERVER_PORT 8596 
#define MESSAGE_LENGTH 1024

int ret = -1;
int socket_fd;
//server addr
struct sockaddr_in serverAddr;

serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVER_PORT);
//inet_addr()函数,将点分十进制IP转换成网络字节序IP
serverAddr.sin_addr.s_addr = inet_addr(args[1]);
if(connect(socket_fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0){
    perror("connect error");
    return 1;
}

三、send

3.1、原型

cpp 复制代码
ssize_t send(int sockfd, const void *buf, size_t len, int flags);

send 是一个在网络编程中使用的函数,用于发送数据到已连接的套接字或发送数据报套接字中。

入参:

  • sockfd:整型参数,表示要发送数据的套接字的文件描述符。
  • buf:指向要发送数据的缓冲区的指针。
  • len:无符号整型参数,表示要发送数据的长度。
  • flags:整型参数,用于指定发送操作的可选标志。常见的标志包括 0(无特殊标志)和 MSG_DONTWAIT(非阻塞模式发送)等。

返回值

  • 如果成功发送数据,send 返回发送的字节数。
  • 如果连接关闭(对于流套接字)或发送超时(对于数据报套接字),send 返回 0。
  • 如果发生错误,send 返回 -1,并设置相应的错误码,可以通过 errno 全局变量获取具体的错误信息。

3.2、源码

cpp 复制代码
#define MESSAGE_LENGTH 1024

char sendbuf[MESSAGE_LENGTH];

 while(1)
  {
    memset(sendbuf, 0, MESSAGE_LENGTH);

    printf("send message:");

    fgets(sendbuf,MESSAGE_LENGTH,stdin);
    //printf("\n");
    ret = send(socket_fd, sendbuf, strlen(sendbuf), 0);
    if(ret <= 0 ){
      printf("the connection is disconnection!\n");
      break;
    }

  }

四、recv

4.1、原型

cpp 复制代码
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

recv 是一个在网络编程中使用的函数,用于接收数据从已连接的套接字或接收数据报套接字中。

需要注意的是,recv 函数是一个阻塞调用,即在没有数据到达之前,它会一直等待。如果需要非阻塞的操作,可以使用非阻塞 I/O 或多线程/多进程的方式处理接收操作。

入参:

  • sockfd:整型参数,表示要接收数据的套接字的文件描述符。
  • buf:指向接收数据缓冲区的指针,用于存储接收到的数据。
  • len:无符号整型参数,表示接收数据缓冲区的长度。
  • flags:整型参数,用于指定接收操作的可选标志。常见的标志包括 0(无特殊标志)、MSG_DONTWAIT(非阻塞模式接收)和 MSG_WAITALL(阻塞模式接收,直到接收到指定长度的数据)等。

返回值:

  • 如果成功接收数据,recv 返回接收到的字节数。
  • 如果连接关闭(对于流套接字)或接收超时(对于数据报套接字),recv 返回 0。
  • 如果发生错误,recv 返回 -1,并设置相应的错误码,可以通过 errno 全局变量获取具体的错误信息。

五、完整代码

cpp 复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include <errno.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_PORT 8596 
#define MESSAGE_LENGTH 1024

int main(int argc,char* args[])
{

  int ret = -1;
  int socket_fd;

  //server addr
  struct sockaddr_in serverAddr;

  char sendbuf[MESSAGE_LENGTH];
  char recvbuf[MESSAGE_LENGTH];

  int data_len;

  if((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  {
    perror("socket");
    return 1;
  }

  serverAddr.sin_family = AF_INET;
  serverAddr.sin_port = htons(SERVER_PORT);

  //inet_addr()函数,将点分十进制IP转换成网络字节序IP
  serverAddr.sin_addr.s_addr = inet_addr(args[1]);

  if(connect(socket_fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
  {
    perror("connect");
    return 1;
  }

  printf("success to connect server...\n");

  while(1)
  {
    memset(sendbuf, 0, MESSAGE_LENGTH);

    printf("send message:");

    fgets(sendbuf,MESSAGE_LENGTH,stdin);
    //printf("\n");
    ret = send(socket_fd, sendbuf, strlen(sendbuf), 0);
    if(ret <= 0 ){
      printf("the connection is disconnection!\n");
      break;
    }

    if(strcmp(sendbuf, "quit") == 0){
      break;
    }

    printf("receive message:");

    recvbuf[0] = '\0';
    data_len = recv(socket_fd, recvbuf, MESSAGE_LENGTH, 0);

    recvbuf[data_len] = '\0';

    printf("%s\n", recvbuf);

  }

  close(socket_fd);

  return 0;

}
相关推荐
热爱嵌入式的小许3 小时前
Linux基础项目开发1:量产工具——显示系统
linux·运维·服务器·韦东山量产工具
小堃学编程4 小时前
计算机网络(十) —— IP协议详解,理解运营商和全球网络
网络·tcp/ip·计算机网络
小鹿( ﹡ˆoˆ﹡ )7 小时前
探索IP协议的神秘面纱:Python中的网络通信
python·tcp/ip·php
韩楚风7 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
陈苏同学7 小时前
4. 将pycharm本地项目同步到(Linux)服务器上——深度学习·科研实践·从0到1
linux·服务器·ide·人工智能·python·深度学习·pycharm
Pythonliu78 小时前
茴香豆 + Qwen-7B-Chat-Int8
linux·运维·服务器
你疯了抱抱我8 小时前
【RockyLinux 9.4】安装 NVIDIA 驱动,改变分辨率,避坑版本。(CentOS 系列也能用)
linux·运维·centos
我是哈哈hh8 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
郭二哈8 小时前
C++——模板进阶、继承
java·服务器·c++
挥剑决浮云 -8 小时前
Linux 之 安装软件、GCC编译器、Linux 操作系统基础
linux·服务器·c语言·c++·经验分享·笔记