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

2023-09-15 17:51:10

在这里插入图片描述

一、socket

在这里插入图片描述

1.1、vim man查看socket

:!man socket

在这里插入图片描述
在这里插入图片描述

1.2、 依赖的头文件

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

1.3、原型

int socket(int domain, int type, int protocol);
domain说明
AF_INETIPV4协议
AF_INET6IPV6协议
AF_LOCALUnix域协议
type说明
SOCK_STREAM字节流套接字(TCP/SCTP)
SOCK_DGRAM数据报套接字(UDP)
SOCK_RAM原始套接字 (IPv4/IPv6)
SOCK_SEQPACKET有序分组套接字(SCTP)
protocol说明
IPPROTO_CPTCP传输协议
IPPROTO_UDPUDP传输协议
IPPROTO_SCTPSCTP传输协议

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

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

二、connect

在这里插入图片描述

2.1、原型

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

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

入参:

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

返回值:

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

2.2、代码

#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、原型

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、源码

#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、原型

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 全局变量获取具体的错误信息。

五、完整代码

#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;

}

更多推荐

JVM面试题-JVM对象的创建过程、内存分配、内存布局、访问定位等问题详解

对象内存分配的两种方式指针碰撞适用场合:堆内存规整(即没有内存碎片)的情况下。原理:用过的内存全部整合到一边,没有用过的内存放在另一边,中间有一个分界指针,只需要向着没用过的内存方向将该指针移动对象内存大小位置即可。使用该分配方式的GC收集器:Serial,ParNew空闲列表适用场合:堆内存不规整的情况下。原理:虚拟

解决npm install遇到的问题:Error while executing:

目录一、遇到问题二、解决办法方法一方法二方法三方法四一、遇到问题npmERR!Errorwhileexecuting:npmERR!D:\IT_base\git\Git\cmd\git.EXEls-remote-h-tssh://git@github.com/sohee-lee7/Squire.gitnpmERR!np

Python爬虫如何使用代理IP进行抓取

前言Python爬虫是一种非常强大的工具,可以用于抓取各种网站的数据。但是,在一些情况下,我们需要使用代理IP来完成数据抓取,如绕过IP限制或保护隐私信息等。本文将介绍如何使用Python爬虫抓取数据时使用代理IP,并提供示例代码和注意事项。一、什么是代理IP代理IP是一种充当客户端和服务器之间中间人的IP地址。客户端

python爬虫:同步模式和异步模式的区别

简单介绍区别Python爬虫可以使用同步模式和异步模式来执行任务,这两种模式有不同的工作方式和优缺点。下面是它们之间的主要区别:同步模式:同步模式是传统的编程方式,代码按照顺序执行,每个操作都会阻塞当前线程直到完成。当一个请求或操作需要时间较长时,程序将被阻塞,等待结果返回,这可能导致程序性能较低,尤其在大量IO密集型

浅谈C++|类的成员

一.类对象作为类成员类可以作为另一个类的成员代码:#include<iostream>usingnamespacestd;classphone{public:stringshouji;phone(stringshouji1):shouji(shouji1){cout<<"phone的构造函数调用"<<endl;}~ph

Java基于SpingBoot的地方废物回收机构管理系统,可作为毕业设计

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W+,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌文章目录1.简介2.技术栈3.可行性分析四系统设计第五章系统功能实现5.1管理员功能模块六、源码获取1.简介地方废物回收机构的需求和管理上的不断提升,地

第23章_瑞萨MCU零基础入门系列教程之ADC与DSP

本教程基于韦东山百问网出的DShanMCU-RA6M5开发板进行编写,需要的同学可以在这里获取:https://item.taobao.com/item.htm?id=728461040949配套资料获取:https://renesas-docs.100ask.net瑞萨MCU零基础入门系列教程汇总:https://b

Java环境搭建&安装IDE

Java环境搭建、安装IDE文章目录Java环境搭建、安装IDE1.下载JavaJDK,配置环境变量,在命令行环境下完成helloworld程序;简介安装Step0安装包准备工作Step1下载JavaJDKStep2配置环境变量配置JAVA_HOME配置Path配置CLASSPATHStep4检验运行程序2.选择一款自

C++之浅拷贝、深拷贝、拷贝构造函数、拷贝赋值运算符、自定义的深拷贝函数应用总结(二百二十九)

简介:CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注:Android系统攻城狮1.前言本篇目的:理解C+

数据库锁及批量更新死锁处理

数据库锁锁间隙锁锁定的是一个间隙范围,而不会锁住某条记录。共享锁就是读锁,独占锁就是写锁,可以理解为读写锁,读读不互斥,读写互斥,写写互斥,共享锁(S锁)、独占锁(X锁)指的就是InnoDB上的行锁(记录锁)。意向锁是InnoDB引擎的一种特殊的表锁,在获取共享锁和独占锁之前必须拿到对应类型的意向锁。乐观锁和悲观锁更多

如何处理ChatGPT在文本生成中的语法错误和不合理性?

ChatGPT是一种强大的自然语言处理模型,但它并不是完美的,有时会产生语法错误或不合理的文本。这些问题可能会影响模型生成的内容的质量和可信度。在处理ChatGPT中的语法错误和不合理性时,有许多方法和策略可以采用,以下是一些详细的讨论:**1.数据清洗和预处理:**首先,可以通过对输入数据进行清洗和预处理来减少语法错

热文推荐