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网络编程的相关介绍及案例。感谢大家的阅读,希望对各位有所帮助。