当前位置:首页 > 行业动态 > 正文

如何区分C语言中的客户端与服务器端?

客户端与服务器端是计算机网络中的两个基本概念,分别指代不同的计算设备或程序。

在网络编程中,客户端和服务器端的交互是构建分布式系统的基础,使用C语言进行网络编程时,通常会涉及到套接字(socket)的使用,这是一种进程间通信的方式,下面将详细介绍如何使用C语言编写一个简单的客户端和服务器端程序。

如何区分C语言中的客户端与服务器端?  第1张

服务端程序

1、创建套接字:需要创建一个套接字来监听客户端的连接请求,可以使用socket()函数来创建一个新的套接字,该函数的原型如下:

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

domain指定协议族,常用的有AF_INET(IPv4)和AF_INET6(IPv6),type指定套接字类型,常用的有SOCK_STREAM(流套接字,用于TCP)和SOCK_DGRAM(数据报套接字,用于UDP),protocol通常设置为0,表示使用默认协议。

2、绑定套接字:需要将套接字绑定到一个特定的端口号和IP地址,可以使用bind()函数来完成这个操作:

 struct sockaddr_in address;
   address.sin_family = AF_INET;
   address.sin_addr.s_addr = INADDR_ANY;
   address.sin_port = htons(PORT);
   if (bind(server_socket, (struct sockaddr *)&address, sizeof(address)) < 0) {
       perror("bind failed");
       close(server_socket);
       exit(EXIT_FAILURE);
   }

3、监听连接请求:绑定成功后,服务器需要开始监听来自客户端的连接请求,可以使用listen()函数来实现:

 if (listen(server_socket, 3) < 0) {
       perror("listen failed");
       close(server_socket);
       exit(EXIT_FAILURE);
   }

4、接受连接请求:当有客户端连接请求时,服务器需要接受这个请求,并创建一个新的套接字来与客户端通信,可以使用accept()函数来实现:

 int addrlen = sizeof(address);
   int new_socket = accept(server_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen);
   if (new_socket < 0) {
       perror("accept failed");
       close(server_socket);
       exit(EXIT_FAILURE);
   }

5、处理数据传输:服务器端可以使用read()和write()函数来接收和发送数据,以下是一个简单的例子,服务器接收客户端发送的数据并回传给客户端:

 char buffer[1024] = {0};
   int valread = read(new_socket, buffer, 1024);
   printf("Received: %s
", buffer);
   write(new_socket, buffer, strlen(buffer));

客户端程序

1、创建套接字:客户端也需要创建一个套接字,使用方法与服务器端相同:

 int client_socket = socket(AF_INET, SOCK_STREAM, 0);
   if (client_socket < 0) {
       perror("socket failed");
       exit(EXIT_FAILURE);
   }

2、连接到服务器:客户端需要连接到指定的服务器IP地址和端口号,可以使用connect()函数来实现:

 struct sockaddr_in serv_addr;
   serv_addr.sin_family = AF_INET;
   serv_addr.sin_port = htons(PORT);
   if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
       perror("Invalid address or address not supported");
       close(client_socket);
       exit(EXIT_FAILURE);
   }
   if (connect(client_socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
       perror("Connection failed");
       close(client_socket);
       exit(EXIT_FAILURE);
   }

3、处理数据传输:客户端可以使用send()和recv()函数来发送和接收数据,以下是一个简单的例子,客户端发送数据到服务器并接收服务器的回传数据:

 char *message = "Hello, Server!";
   send(client_socket, message, strlen(message), 0);
   printf("Message sent
");
   char buffer[1024] = {0};
   int valread = recv(client_socket, buffer, 1024, 0);
   printf("Received: %s
", buffer);

错误处理

在网络编程中,错误处理是非常重要的,需要确保在每个系统调用之后检查返回值,并在出现错误时进行适当的处理。

if (server_socket < 0) {
    perror("socket failed");
    exit(EXIT_FAILURE);
}

完整示例代码

服务器端代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
      
    // Creating socket file descriptor
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
      
    // Forcefully attaching socket to the port 8080
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
      
    // Forcefully attaching socket to the port 8080
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }
      
    char buffer[1024] = {0};
    int valread = read(new_socket, buffer, 1024);
    printf("%s
",buffer);
    send(new_socket, buffer, strlen(buffer), 0);
    printf("Hello from server
");
    return 0;
}

客户端代码

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define PORT 8080
int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    char *hello = "Hello from client";
    char buffer[1024] = {0};
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("
 Socket creation error 
");
        return -1;
    }
  
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
      
    // Convert IPv4 and IPv6 addresses from text to binary form
    if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {
        printf("
Invalid address/ Address not supported 
");
        return -1;
    }
  
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        printf("
Connection Failed 
");
        return -1;
    }
    send(sock, hello, strlen(hello), 0);
    printf("Hello message sent
");
    valread = read(sock, buffer, 1024);
    printf("%s
",buffer);
    return 0;
}
0