首页 技术 正文
技术 2022年11月14日
0 收藏 960 点赞 2,424 浏览 3600 个字

Linux下的C Socket编程(三)

server端的简单示例

经过前面的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的一个端口上面去。

绑定socket到一个端口上

bind()函数可以将socket绑定到一个端口上,client可以通过向这个端口发起请求,端口对应的socket便会与client端的socket连接。

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>int main() {
int socket_desc;
struct sockaddr_in server;socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == socket_desc) {
perror("cannot create socket");
exit(1);
}// 监听服务器自身
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons(8888);// 绑定到端口
if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("cannot bind error");
exit(1);
}printf("bind success");close(socket_desc);
return 0;
}

对于server.sin_addr.s_addr的更多信息可以参考这里

通过将socket绑定到一个确定的端口上,我们接下来要做的便是接收这个端口下的所有数据。

通过上面的实现,可以看出一个端口只能被一个socket使用。

监听端口

在绑定玩socket与端口后,我们还需要去监听端口。为此,我们需要将socket设置在被监听的状态下。listen()被用来将socket设置为被监听的模式下。

listen(socket_desc, 3);

listen(int sockfd, int backlog)可以将socket处于监听的状态。

其参数为:

  1. int sockfd 设置监听的socket
  2. int backlog在当前连接后面允许存在的最大未处理连接数

当监听到新的请求来临时,server需要接收请求建立连接。

接收请求建立连接

函数accept()的作用便是接收请求。

#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>int main() {
int socket_desc, new_socket, sockaddr_size;
struct sockaddr_in server, client;// 创建socket
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == socket_desc) {
perror("cannot create socket");
exit(1);
}server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons(8888);// 绑定
if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("bind error");
exit(1);
}// 监听
listen(socket_desc, 5);puts("waiting for incoming connections....");// 接受
sockaddr_size = sizeof(struct sockaddr_in);
new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t *)&sockaddr_size);
if (new_socket < 0) {
perror("accept error");
exit(1);
}puts("connection accepted");
// 先关闭由socket_desc产生的new_socket
close(new_socket);
// 在关闭socket_desc
close(socket_desc);
return 0;
}

运行代码,他将会输出:

waiting for incoming connections....

现在代码已经正常的跑起来了,并且等待请求连接。在另外一个终端内,我们发起一个请求:

telnet 127.0.0.1 8888

在当前的这个终端内将会输出:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

同时在之前的终端内,server会输出:

waiting for incoming connections....
connection accepted

便可以看到server已经正确的接受了client的连接请求并建立了连接,只是没有后续操作,主机紧接着关闭了这个连接。

连接建立之后便可以顺利的进行双方的通信,这部分的sendrecv操作完全一样。

另外:

服务端获取客户端的IP地址

由前面能够知道accept()返回的是结构体sockaddr_in,由此很容易得知client的IP和端口信息。

char *client_ip = inet_ntoa(client.sin_addr);
int client_port = ntohs(client.sin_port);
server端的总结:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>int main() {
int socket_desc, new_socket;
struct sockaddr_in server, client;
char *message, get_recv[2000];// 创建socket
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == socket_desc) {
perror("cannot create socket");
exit(1);
}server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons(8888);// 绑定
if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("cannot bind");
exit(1);
}
puts("bind success");// 监听
listen(socket_desc, 5);
puts("waiting for incoming connections....");// 接受连接
socklen_t sockaddr_size = sizeof(client);
new_socket = accept(socket_desc, (struct sockaddr *)&client, &sockaddr_size);if (new_socket < 0) {
perror("accept error");
exit(1);
}
puts("connection accepted");// 发送数据
message = "hello world\r\n";
if (send(new_socket, message, strlen(message), 0) < 0) {
perror("send message error");
return 1;
}
puts("send message success");if (recv(new_socket, get_recv, 2000, 0) < 0) {
perror("recv error");
return 2;
}
puts("recv success");
puts(get_recv);// 关闭
close(new_socket);
close(socket_desc);
return 0;
}

到目前为止,server端的主要操作都已经完成,接下来便是对server端的深入处理,使得server端能够一直不断的接受处理连接请求。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,086
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,561
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,410
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,183
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,820
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,903