Linux网络编程:socket编程

Linux网络编程——socket编程

欢迎来到我的博客,今天我们将着眼于Linux上的socket网络编程。先来介绍下什么是socket。在计算机网络中,socket是一种网络通信的机制,让不同主机的程序能够互相通信。Linux下的socket网络编程提供了相对方便,鲁棒的接口和实现。

下面,我们进入正题:如何进行Linux socket网络编程?

步骤一:创建一个socket descripter

使用socket()函数创建一个socket文件描述符。socket()函数的原型如下:

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

该函数创建一个socket描述符并返回一个整数值。其中的domain指定协议族,type指定传输协议的类型,protocol指定通信协议的协议编号。例如,下面的代码创建了一个TCP协议的socket描述符:

int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
  perror("socket() error");
  exit(1);
}

步骤二:绑定IP地址和端口号

使用bind()函数将一个特定的IP地址和端口号绑定到socket()函数返回的socket描述符上。bind()函数的原型如下:

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

该函数将socket描述符与本地IP地址和端口号进行绑定。sockfd是socket描述符,addr是指向sockaddr类型结构体的指针,addrlen为sockaddr结构体的大小。示例代码如下:

struct sockaddr_in serv_addr;
bzero((char*)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno); //定义portno的端口号
if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){
  perror("bind() error");
  exit(1);
}

步骤三:监听socket

接下来要让socket监听客户端的连接请求。使用listen()函数将socket变为可被动连接的socket。listen()函数的原型如下:

int listen(int sockfd, int backlog);

该函数使socket变为可被动连接模式,sockfd为socket描述符,backlog表示socket允许的最大连接数。示例代码如下:

if(listen(sockfd, 5) < 0){
  perror("listen() error");
  exit(1);
}

步骤四:接受连接请求

使用accept()函数接受客户端的连接请求。accept()函数的原型如下:

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

该函数将sockfd套接字接受来自客户端的连接请求,并在新创建的套接字中返回另一个socket描述符。如果有客户端连接,则accept()函数就会立即成功返回。其中,addr指向客户端地址结构的指针,addrlen为客户端地址结构的大小。示例代码如下:

int newsockfd;
struct sockaddr_in cli_addr;
socklen_t clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
if(newsockfd < 0){
  perror("accept() error");
  exit(1);
}

步骤五:发送和接收数据

新创建的socket描述符实际上是一个可以进行数据传输的管道。我们使用send()函数和recv()函数进行数据传输。send()函数的原型如下:

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

该函数将缓冲区中的数据发送到已连接的socket描述符sockfd。buf是一个指向待发送数据的指针,len是数据的长度,flags是传输时设置的选项。recv()函数的原型如下:

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

该函数从已连接的socket描述符sockfd接收消息,并保存到缓冲区指针buf中。len是缓冲区的大小,flags是传输时设置的选项。示例代码如下:

char buffer[256];
bzero(buffer, sizeof(buffer));
n = recv(newsockfd, buffer, sizeof(buffer)-1, 0);
if(n < 0) {
   perror("recv() error");
   exit(1);
}
printf("Here is the message: %s\n", buffer);
n = send(newsockfd, "I got your message", 18, 0);
if(n < 0) {
   perror("send() error");
   exit(1);
}

以上就是Linux上socket网络编程的基本步骤。

接下来,为了更好地理解和学习,这里给大家提供一个简单的例子,客户端与服务端可以相互交流发信息。大家可以在代码中设置自己的ip地址和端口号,在虚拟机上编译运行。

服务器端代码:

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
//#include<linux/in.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int main()
{
        char readBuf[128];
        int n_read;
        char *reply = "I get your message";

        struct sockaddr_in s_addr;
        struct sockaddr_in c_addr;

        memset(&s_addr,0,sizeof(struct sockaddr_in));
        memset(&c_addr,0,sizeof(struct sockaddr_in));

        //1.socket  int socket(int domain, int type, int protocol);

        int s_fd;

        s_fd = socket(AF_INET,SOCK_STREAM,0);
        if(s_fd == -1){
                perror("socket");
                exit(-1);
        }
        
        //2.bind
        //struct sockaddr_in s_addr;
        s_addr.sin_family = AF_INET;//协议
        s_addr.sin_port = htons(8988);//端口号
        inet_aton("192.168.163.128",&s_addr.sin_addr);//IP地址

        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

        //3.listen
        listen(s_fd,10);

        //4.accept
        int clen = sizeof(struct sockaddr_in);
        int c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);
        if(c_fd == -1){
                perror("accept");
        }
        printf("welcome to connect server:%s\n",inet_ntoa(c_addr.sin_addr));

        //5.read
        n_read = read(c_fd,readBuf,128);
        if(n_read == -1){
                perror("read");
        }else{
                printf("get message:%d,%s\n",n_read,readBuf);
        }

        //6.write
        write(c_fd,reply,strlen(reply));

        return 0;
}

客户端代码:

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
//#include<linux/in.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int main()
{
        char readBuf[128];
        int n_read;
        char *reply = "reply from client";

        struct sockaddr_in c_addr;

        memset(&c_addr,0,sizeof(struct sockaddr_in));

        //1.socket  int socket(int domain, int type, int protocol);

        int c_fd;

        c_fd = socket(AF_INET,SOCK_STREAM,0);
        if(c_fd == -1){
                perror("socket");
                exit(-1);
        }

        c_addr.sin_family = AF_INET;//协议
        c_addr.sin_port = htons(8988);//端口号
        inet_aton("192.168.163.128",&c_addr.sin_addr);//IP地址

        //2.connect
        if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){
                perror("connect");
                exit(-1);
        }

        //3.send        
        write(c_fd,reply,strlen(reply));

        //4.read
        n_read = read(c_fd,readBuf,128);
        if(n_read == -1){
                perror("read");
        }else{
                printf("get message from server:%d,%s\n",n_read,readBuf);
        }

        return 0;

以上就是基于socket的Linux网络编程的相关介绍及案例。感谢大家的阅读,希望对各位有所帮助。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值