Linux下的C Socket编程 -- server端的简单示例
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处于监听的状态。
其参数为:
- int sockfd 设置监听的socket
- 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的连接请求并建立了连接,只是没有后续操作,主机紧接着关闭了这个连接。
连接建立之后便可以顺利的进行双方的通信,这部分的send与recv操作完全一样。
另外:
服务端获取客户端的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端能够一直不断的接受处理连接请求。
Linux下的C Socket编程 -- server端的简单示例的更多相关文章
- Linux下的C Socket编程 -- server端的继续研究
Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...
- Linux下的C Socket编程 -- 简介与client端的处理
Linux下的C Socket编程(一) 介绍 Socket是进程间通信的方式之一,是进程间的通信.这里说的进程并不一定是在同一台机器上也有可能是通过网络连接的不同机器上.只要他们之间建立起了sock ...
- Linux下的C Socket编程 -- 获取对方IP地址
Linux下的C Socket编程(二) 获取域名对应的IP地址 经过上面的讨论,如果我们想要连接到远程的服务器,我们需要知道对方的IP地址,系统函数gethostbyname便能够实现这个目的.它能 ...
- Linux下的C++ socket编程实例
阅读目录 基本的局域网聊天 客户端服务端双向异步聊天源码 局域网内服务端和有限个客户端聊天源码 完美异步聊天服务端和客户端源码 C++定时器 select异步代码 pthead多线程 服务端: 服务器 ...
- Python中Socket编程server与client简单的合法性认证
导入python自带的hmac模块对随机生成的位数32字节和自定义token进行加密处理 import osmsg = os.urandom(32) #随机生成msgOut[4]: b"F ...
- Linux下高并发网络编程
Linux下高并发网络编程 1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时, 最高的并发数量都要受到系统对用户单一进程同时可打 ...
- Linux下高并发socket最大连接数所受的各种限制(详解)
1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每 ...
- 从Linux源码看Socket(TCP)Client端的Connect
从Linux源码看Socket(TCP)Client端的Connect 前言 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情. 今天笔者就来从Linux源码的 ...
- Linux下编译安装Apache Http Server
Linux下编译安装Apache Http Server [TOC] 1.下载httpd-2.4.12.tar.bz2 wget http://mirror.bit.edu.cn/apache/htt ...
随机推荐
- jQuery的DOM操作实例(2)——拖拽效果&&拓展插件
一.原生JavaScript编写拖拽效果 二.jQuery编写的拖拽效果 三.在jQuery中拓展一个拖拽插件
- # ios开发 @property 和 Ivar 的区别
ios开发 @property 和 Ivar 的区别 @property 属性其实是对成员变量的一种封装.我们先大概这样理解: @property = Ivar + setter + getter I ...
- 你真的会玩SQL吗?透视转换的艺术
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 3.JAVA之GUI编程Frame窗口
创建图形化界面思路: 1.创建frame窗体: 2.对窗体进行基本设置: 比如大小.位置.布局 3.定义组件: 4.将组件通过add方法添加到窗体中: 5.让窗体显示,通过setVisible(tur ...
- [原创]django+ldap实现单点登录(装饰器和缓存)
前言 参考本系列之前的文章,我们已经搭建了ldap并且可以通过django来操作ldap了,剩下的就是下游系统的接入了,现在的应用场景,我是分了2个层次,第一层次是统一认证,保证各个系统通过ldap来 ...
- C#组件系列——又一款Excel处理神器Spire.XLS,你值得拥有(二)
前言:上篇 C#组件系列——又一款Excel处理神器Spire.XLS,你值得拥有 介绍了下组件的两个功能,说不上特色,但确实能解决我们项目中的一些实际问题,这两天继续研究了下这个组件,觉得有些功能用 ...
- 利用Vue.js实现拼图游戏
之前写过一篇<基于Vue.js的表格分页组件>的文章,主要介绍了Vue组件的编写方法,有兴趣的可以访问这里进行阅读:http://www.cnblogs.com/luozhihao/p/5 ...
- Oracle 内置sql函数大全
F.1字符函数--返回字符值 这些函数全都接收的是字符族类型的参数(CHR除外)并且返回字符值.除了特别说明的之外,这些函数大部分返回VARCHAR2类型的数值.字符函数的返回类型所受的限制和基本数据 ...
- Ionic2系列-将beta升级到RC1
国庆节前Ionic2发布了RC0版本,已经接近正式版了,前不久Angular2和TypeScript2也已经发布了正式版.详情请参考官方博客: http://blog.ionic.io/announc ...
- 【无私分享:ASP.NET CORE 项目实战(第八章)】读取配置文件(二) 读取自定义配置文件
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 我们在 读取配置文件(一) appsettings.json 中介绍了,如何读取appsettings.json. 但随之产生 ...