进阶:深入理解Linux Socket编程 (linux socket学习 十六)

在计算机网络领域,Socket编程是一项非常基础而重要的技能。由于Linux操作系统的普及,学习和掌握Linux Socket编程技术成为了许多开发者的必修课程。本文将从原理、流程、实现等多个角度深入分析Linux Socket编程,为读者提供更深层次的理解和掌握。

一、Socket的基本原理

Socket是一个在应用层和传输层之间的一个抽象层,它为应用程序提供了一种通信机制,使应用程序可以通过网络进行数据交换。Socket以IP地址和端口号作为网络通信的唯一标识,通过这两个标识可以实现网络通信。

可以将Socket分成两个部分:服务器端和客户端。服务器端开启一个Socket监听,等待客户端发送数据;客户端开启一个Socket连接到服务器端以发送和接收数据。在Linux操作系统中,Socket通信是基于文件描述符的,因此Socket的使用方式和其他文件描述符一样,包括创建Socket、打开Socket、读写Socket等操作。

二、Socket通信流程

Socket通信通常包含以下五个步骤:

1. 创建Socket

在Linux中,Socket通信使用socket()函数创建Socket。socket()函数会返回Socket的文件描述符,Socket通信就是通过这个文件描述符进行的。

2. 绑定SocketAddress

绑定SocketAddress通常指定IP地址和端口号,用于对Socket进行标识并监听。bind()函数用于将指定的SocketAddress绑定到一个创建好的Socket上,从而使创建的Socket与指定的SocketAddress关联起来。

3. 监听Socket

通过listen()函数使Socket处于连接状态,接受来自客户端的连接请求。

4. 接受客户端连接

accept()函数用于从处于连接状态的Socket中接受一个客户端连接请求,从而建立一个客户端和服务器端之间的连接。

5. 发送和接收数据

建立连接后,客户端和服务器端可以通过send()和recv()函数互相发送和接收数据。send()函数用于发送数据,recv()函数用于接收数据。

三、Socket通信实现

了解了Socket的基本原理和通信流程,下面通过一个简单的例子来实现Socket通信。假设有两台计算机,一台作为服务器,另一台作为客户端。

服务器端:

1. 创建Socket

“`cpp

// 创建Socket

int listen_fd = socket(AF_INET, SOCK_STREAM, 0);

if (listen_fd

perror(“socket() error”);

exit(-1);

}

“`

2. 绑定SocketAddress

“`cpp

// 绑定SocketAddress

struct sockaddr_in serv_addr;

memset(&serv_addr, 0, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;

serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

serv_addr.sin_port = htons(port);

if (bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))

perror(“bind() error”);

exit(-1);

}

“`

3. 监听Socket

“`cpp

// 监听Socket

if (listen(listen_fd, SOMAXCONN)

perror(“listen() error”);

exit(-1);

}

“`

4. 接受客户端连接

“`cpp

// 接受客户端连接

struct sockaddr_in cli_addr;

socklen_t cli_size = sizeof(cli_addr);

int conn_fd = accept(listen_fd, (struct sockaddr *)&cli_addr, &cli_size);

if (conn_fd

perror(“accept() error”);

exit(-1);

}

“`

5. 发送和接收数据

“`cpp

// 发送和接收数据

char buf[1024];

while (true) {

memset(buf, 0, sizeof(buf));

int n = recv(conn_fd, buf, sizeof(buf), 0);

if (n

perror(“recv() error”);

exit(-1);

} else if (n == 0) {

break;

}

printf(“recv msg: %s\n”, buf);

n = send(conn_fd, buf, strlen(buf), 0);

if (n

perror(“send() error”);

exit(-1);

}

}

“`

客户端:

1. 创建Socket

“`cpp

// 创建Socket

int conn_fd = socket(AF_INET, SOCK_STREAM, 0);

if (conn_fd

perror(“socket() error”);

exit(-1);

}

“`

2. 连接服务器

“`cpp

// 连接服务器

struct sockaddr_in serv_addr;

memset(&serv_addr, 0, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;

serv_addr.sin_port = htons(port);

if (inet_pton(AF_INET, addr, &serv_addr.sin_addr)

perror(“inet_pton() error”);

exit(-1);

}

if (connect(conn_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))

perror(“connect() error”);

exit(-1);

}

“`

3. 发送和接收数据

“`cpp

// 发送和接收数据

char buf[1024];

while (true) {

memset(buf, 0, sizeof(buf));

scanf(“%s”, buf);

int n = send(conn_fd, buf, strlen(buf), 0);

if (n

perror(“send() error”);

exit(-1);

}

n = recv(conn_fd, buf, sizeof(buf), 0);

if (n

perror(“recv() error”);

exit(-1);

} else if (n == 0) {

break;

}

printf(“recv msg: %s\n”, buf);

}

“`

通过以上代码,客户端和服务器端基本实现了Socket通信。值得注意的是,Socket通信在处理时必须注意多线程、异步IO等问题,以避免阻塞或者崩溃的风险。

总体来说,Socket编程是一项重要的系统编程任务,涉及多个领域的知识和技能。本文从基本原理、通信流程、实现操作三个角度深入剖析了Linux Socket编程技术,希望能对读者提供进一步的学习和掌握帮助。

相关问题拓展阅读:

求大神解惑 linux socket编程的几个不懂地方

(struct sockaddr *)(&server_addr) 的意思是把server_addr的地址强转成struct sockaddr *类型的地址,记住指针吵伏罩即地址。

if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1)的&sin_size和前面的厅辩什么sizeof无关,这一个为了获取别人存升闹取的client_addr数据的大小,意思就是你给个地址别人给你把连接你的客户端的数据存到地址里去而已,你要把函数通过参数地址获取和得到数据的情况分清楚。

linux下C语言socket编程双机互发数据

这么专业的问题去专业的网站或搜索QQ群上问吧,百度里有空回答的怕没几个人知道。

这个问题很好办啦,服务器接受一个连接请求,然后开一个线程或者进程都可以,再在线程或者进程里面采用其他技术实现同时收发(比如I/O复用,比如非阻塞I/O)。客户端也可以采用I/O复用。

推荐资含尺拦料的话,《unix网络编程》这本书很好,公认的经典,当教科书用,这本书里有你想要的所有内容。

ps:你基础太差,多补补吧,别想一下吃困桐个胖子。

另外我这里正好有个例子满足你的要求,贴给你,自己写的,不是网上找的,用的是多进程加I/O复用技术:

server端:

/****************************************************************

**

**

**

****************************************************************/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define BUFLEN 1024

#define MAX(a,b) ((a)>(b)?(a):(b))

typedef void Sigfunc (int);

void str_echo(FILE *,int);

//Sigfunc *signal(int, Sigfunc *);

int main(int argc,char **argv)

{

int connfd,listenfd;

pid_t childpid;

socklen_t clilen;

struct sockaddr_in cliaddr,servaddr;

void sig_chld(int);

listenfd = socket(AF_INET, SOCK_STREAM, 0);

memset(&servaddr,0,sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

servaddr.sin_port = htons(5358);

bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));

listen(listenfd,8);

signal(SIGCHLD,sig_chld);

while(1)

{

clilen = sizeof(cliaddr);

if((connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&clilen)) 0)

{

printf(“child %d terminated\n”,pid);

}

return;

}

client端:

#include

#include

#include

#include

#include

#include

#include

#define MAX(a,b) (a)>(b)?(a):(b)

int main()

{

int s,connectReturn, maxfd;

fd_set rset;

char sendbuf = {0};

char recvbuf = {0};

long port=5358;

s=socket(PF_INET,SOCK_STREAM,0);

struct sockaddr_in sa;

sa.sin_family=AF_INET;

sa.sin_addr.s_addr=inet_addr(“127.0.0.1”);

sa.sin_port=htons(port);

connectReturn=connect(s,(struct sockaddr *)&sa,sizeof(sa));

printf(“%d\n”,connectReturn);

FD_ZERO(&rset);

while(1)

{

FD_SET(fileno(stdin), &rset);

FD_SET(s, &rset);

maxfd=MAX(fileno(stdin), s) + 1;

select(maxfd, &rset, NULL, NULL, NULL);

if(FD_ISSET(fileno(stdin), &rset))

{

scanf(“%s”,sendbuf);

send(s,sendbuf,strlen(sendbuf),0);

bzero(sendbuf, 1024);

}

else if(FD_ISSET(s, &rset))

{

memset(recvbuf,0,1024);

recv(s,recvbuf,1024,0);

printf(“remote: %s\n”,recvbuf);

}

}

return 0;

关于linux socket学习 十六的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 进阶:深入理解Linux Socket编程 (linux socket学习 十六)