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端能够一直不断的接受处理连接请求。

Linux下的C Socket编程 -- server端的简单示例的更多相关文章

  1. Linux下的C Socket编程 -- server端的继续研究

    Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...

  2. Linux下的C Socket编程 -- 简介与client端的处理

    Linux下的C Socket编程(一) 介绍 Socket是进程间通信的方式之一,是进程间的通信.这里说的进程并不一定是在同一台机器上也有可能是通过网络连接的不同机器上.只要他们之间建立起了sock ...

  3. Linux下的C Socket编程 -- 获取对方IP地址

    Linux下的C Socket编程(二) 获取域名对应的IP地址 经过上面的讨论,如果我们想要连接到远程的服务器,我们需要知道对方的IP地址,系统函数gethostbyname便能够实现这个目的.它能 ...

  4. Linux下的C++ socket编程实例

    阅读目录 基本的局域网聊天 客户端服务端双向异步聊天源码 局域网内服务端和有限个客户端聊天源码 完美异步聊天服务端和客户端源码 C++定时器 select异步代码 pthead多线程 服务端: 服务器 ...

  5. Python中Socket编程server与client简单的合法性认证

    导入python自带的hmac模块对随机生成的位数32字节和自定义token进行加密处理 import osmsg = os.urandom(32)  #随机生成msgOut[4]: b"F ...

  6. Linux下高并发网络编程

      Linux下高并发网络编程 1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时, 最高的并发数量都要受到系统对用户单一进程同时可打 ...

  7. Linux下高并发socket最大连接数所受的各种限制(详解)

    1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每 ...

  8. 从Linux源码看Socket(TCP)Client端的Connect

    从Linux源码看Socket(TCP)Client端的Connect 前言 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情. 今天笔者就来从Linux源码的 ...

  9. Linux下编译安装Apache Http Server

    Linux下编译安装Apache Http Server [TOC] 1.下载httpd-2.4.12.tar.bz2 wget http://mirror.bit.edu.cn/apache/htt ...

随机推荐

  1. java进阶之反射:反射基础之如何获取一个类以及如何获取这个类的所有属性和方法(2)

    当我们知道一个类的对象,或者知道一个类的路径,或者指导这个类的名称的时候我们可以获取到这个类的类对象 当我们仅仅知道一个类的类对象的时候我们依然无法操作这个类,因为我们不知道这个类的属性,类的方法.那 ...

  2. Java 素数 prime numbers-LeetCode 204

    Description: Count the number of prime numbers less than a non-negative number, n click to show more ...

  3. Vertica数据库常用管理命令汇总

    1.查询数据库是否有等待 select * from resource_queues where node_name=(select node_name from nodes order by nod ...

  4. android快捷开发之Retrofit网络加载框架的简单使用

    大家都知道,安卓最大的特点就是开源化,这自然会产生很多十分好用的第三方API,而基本每一个APP都会与网络操作和缓存处理机制打交道,当然,你可以自己通过HttpUrlConnection再通过返回数据 ...

  5. 4.C#WinForm基础图片(显示和隐藏)

    要求: 软件上有一张图片,默认是隐藏的.用户在文本框中输入身份证号(131226198105223452),点击按钮,如果年龄大于18岁,则显示图片. 知识点: 取当前年份,Date Time Now ...

  6. 【中文分词】最大熵马尔可夫模型MEMM

    Xue & Shen '2003 [2]用两种序列标注模型--MEMM (Maximum Entropy Markov Model)与CRF (Conditional Random Field ...

  7. jQuery-1.9.1源码分析系列(三) Sizzle选择器引擎——编译原理

    这一节要分析的东东比较复杂,篇幅会比较大,也不知道我描述后能不能让人看明白.这部分的源码我第一次看的时候也比较吃力,现在重头看一遍,再分析一遍,看能否查缺补漏. 看这一部分的源码需要有一个完整的概念后 ...

  8. Nginx最大客户连接数算法一些遐想

    Nginx最大客户连接数算法一些遐想 现在很多互联网公司都在使用nginx,并且替换掉以前的Apache,nginx的优点就不说了,浅聊两句nginx的某些配置参数,找到这些参数设置的目的和关联性,并 ...

  9. img标签使用绝对路径无法显示图片

    说明:  图片的磁盘路径斜杠使用:右斜杠"\",而图片的网络路径使用左斜杠"/",注意加以区分. 如果这张图片属于服务器图片或者网络图片,我们必须在Img标签里 ...

  10. 随机记录工作中常见的sql用法错误(一)

    没事开始写博客,留下以前工作中常用的笔记,内容不全或者需要补充的可以留言,我只写我常用的. 网上很多类似动软生成器的小工具,这类工具虽然在表关系复杂的时候没什么软用,但是在一些简单的表结构关系还是很方 ...