TCP客户端服务器编程模型:

服务器:

  1. 调用socket函数创建套接字
  2. 调用bind绑定本地IP和端口
  3. 调用listen启动监听(准备好接收客户端链接的队列)
  4. 调用accept从已连接队列中提取第一个连接。(如果没有,会阻塞。)
  5. 调用I/O函数(read/write)与客户端通讯
  6. 调用close关闭套接字。(多个套接字)

客户端:

  1. 调用socket创建套接字
  2. 调用connect连接服务器
  3. 调用I/O函数(read/write)与服务器通讯
  4. 调用close关闭套接字

Linux下和Mac下代码一样的,可能有头文件不太一样,用man命令进去查看即可。

功能:

  1. 客户端连到服务器,服务器打印连接的客户端IP和端口,返回给客户端当前服务器时间。
  2. 服务器加了一个信号捕获函数,ctrl+c停止服务器进程。
  3. 如果不写客户端,使用telnet 127.0.0.1 8888 依然可以收到服务器返回的时间字符串。

服务器代码 time_tcp_server.c:

#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h> #define SERVER_PORT 8888
#define LISTEN_QUEUE_SISE 10 int socketfd; void signal_handler(int signo)
{
printf("this serveice close\n");
close(socketfd);
exit();
} void out_clientinfo(const struct sockaddr_in* outsockaddr)
{
char ipstr[];
memset(ipstr, , sizeof(ipstr));
// 将地址从网络字节序转换为点分十进制
inet_ntop(AF_INET, &outsockaddr->sin_addr.s_addr, ipstr, sizeof(ipstr)); printf("Connected by %s(%d)\n", ipstr, ntohs(outsockaddr->sin_port));
} void dosomething(int fd)
{
//获取系统当前时间
long t = time();
char* times = ctime(&t);
size_t size = strlen(times)*sizeof(char);
//将时间写回到客户端
if(write(fd, times, size) != size)
{
perror("write to client error");
}
} int main(int argc, char const *argv[])
{
if (signal(SIGINT, signal_handler) == SIG_ERR)
{
perror("signal error");
exit();
} // 1 sokect
// AF_INET ipv4
// SOCK_STREAM tcp
if((socketfd = socket(AF_INET, SOCK_STREAM, )) < )
{
perror("socket error");
exit();
} // 2 bind 绑定本地地址和端口
struct sockaddr_in serveraddr;
memset(&serveraddr, , sizeof(serveraddr));
serveraddr.sin_family = AF_INET;//ipv4
serveraddr.sin_port = htons(SERVER_PORT); //端口
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);//响应任意网卡的请求
if(bind(socketfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < )
{
perror("bind error");
exit();
} // 3 listen 启动监听 通知系统接受来自客户端的连接 准备好连接队列
if(listen(socketfd, LISTEN_QUEUE_SISE) < )
{
perror("listen error");
exit();
}
struct sockaddr_in clientaddr;
socklen_t clientaddr_len = sizeof(clientaddr);
while()
{
// 4 accept 从队列拿出第一个
// clientaddr获取客户端的地址信息,是传出参数
int clientfd = accept(socketfd, (struct sockaddr*)&clientaddr, &clientaddr_len);
if (clientfd < )
{
perror("accept error");
continue;
}
// 5 read/write
out_clientinfo(&clientaddr);
dosomething(clientfd); // 6 close
close(clientfd);
} // 6 close
return ;
}

客户端代码time_tcp_client:

#include <sys/socket.h>
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h> #define SERVER_PORT 8888
#define SERVER_IP 127.0.0.1 int main(int argc, char const *argv[])
{
//1 创建socket int socketfd = socket(AF_INET, SOCK_STREAM, );
if (socketfd < )
{
perror("socket error");
exit();
} //2 connect
struct sockaddr_in serveraddr;
memset(&serveraddr, , sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVER_PORT); if(connect(socketfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < )
{
perror("connect error");
exit();
} //3 read write
char buf[];
  //read是阻塞函数 如果服务器没有下发消息,会一直阻塞在这里,知道收到消息。
if (read(socketfd, buf, sizeof(buf)) > )
{
printf("%s",buf);
} //4 close
close(socketfd);
return ;
}

本例只是简单的处理,服务器返回客户端一个时间,然后关闭了socket。

如果要进行双向通信,服务器势必要调用read函数,而read默认阻塞,那么如果客户端不向服务器发送数据,则主线程一直阻塞,其它客户端无法连接成功。这就需要处理高并发问题。

服务器高并发处理的三种方式

  1. 多进程 https://www.cnblogs.com/lan0725/p/11634709.html
  2. 多线程 https://www.cnblogs.com/lan0725/p/11639142.html
  3.  I/O多路复用

macos下简单的socket服务器+客户端的更多相关文章

  1. Linux下简单的socket通信实例

    Linux下简单的socket通信实例 If you spend too much time thinking about a thing, you’ll never get it done. —Br ...

  2. windows下的C++ socket服务器(1)

    windows下的一个C++ socket服务器,用到了C++11的相关内容,现在还不是很完善,以后会不断改进的! #include <winsock2.h>//1 以后会用这种方式对特定 ...

  3. TCP/TP编程 - 一个简单的Linux下C写的socket服务器客户端程序

    服务端: hello_server.c #include <stdio.h> #include <stdlib.h> #include <string.h> #in ...

  4. 最简单的socket服务器与客户端

    服务器: //服务器 #include <stdio.h> #include <netinet/in.h> #include <unistd.h> #include ...

  5. python简单的socket 服务器和客户端

    服务器端代码 if "__main__" == __name__: try: sock = socket.socket(socket.AF_INET, socket.SOCK_ST ...

  6. windows下的C++ socket服务器(2)

    int main(int ac, char *av[]) { ); ) { exit(); } thread t; ) { int socket_fd = accept(tcp_socket, nul ...

  7. windows下的C++ socket服务器(3)

    int make_server_socket(int port) { WSADATA inet_WsaData; WSAStartup(MAKEWORD(), &inet_WsaData); ...

  8. windows下的C++ socket服务器(4)

    void handleAccept(int socket_fd) { ] = { '\0' }; string cmd; string filename; recv(socket_fd, buf, ) ...

  9. c++下基于windows socket的单线程服务器客户端程序(基于TCP协议)

    今天自己编写了一个简单的c++服务器客户端程序,注释较详细,在此做个笔记. windows下socket编程的主要流程可概括如下:初始化ws2_32.dll动态库-->创建套接字-->绑定 ...

随机推荐

  1. jenkins:集成sonar代码扫描+发送邮件

    前提: Jenkins JDK 目录: 1.安装sonar插件:SonarQube Scanner for Jenkins 2.安装SonarQube 3.安装sonar-scanner ++++++ ...

  2. centos7:ssh免密登陆设置

    1.使用root用户登录,进入到目录/root/.ssh 2.执行命令:ssh-keygen -t rsa 一路回车,完成后会在目录/root/.ssh下面生成文件 id_rsa和id_rsa.pub ...

  3. Python3 Selenium自动化web测试 ==> 第一节 起始点之Python单元测试框架 unittest

    前置步骤 Python版本:3.6.4 selenium版本:3.11.0 >>> import selenium >>> help(selenium) IDE:P ...

  4. 刀塔OMG塔防1.26b单机版使用方法

    使用方法 1.确保魔兽的版本为1.26以上(低版本会报错),如果版本不对用附件中的版本转换器转一下 2.把 omg.w3x 复制到 魔兽的MAPS文件夹 WarcraftIII 游戏根目录\Maps\ ...

  5. webdriver(处理select下拉框元素)

    """处理下拉框""" from selenium import webdriver from selenium.webdriver.com ...

  6. 【OpenCV开发】使用OpenCV的OpenCL(ocl)模块

    参加OpenCV的OpenCL模块(以下称OCL)移植工作已经有2个月了.这里我说移植而不是开发,是因为大部分OCL模块的函数都是从已经很成熟的GPU模块移植过来的.于是目前阶段OCL模块所支持的函数 ...

  7. thinkphp5 默认配置代码

    <?php // +---------------------------------------------------------------------- // | ThinkPHP [ ...

  8. C#实现工作日和休息日(包括法定节假日)的计算

    转自:http://www.cnblogs.com/yuan-chong/p/HolidayHelper.html 一.开发背景: 最近在公司开发的系统中,需要计算工作日,就是给出一个采购周期(n天) ...

  9. .Net WebApi接口之Swagger集成详解

    本文详细的介绍了.net从一个新的项目中创建api后集成swagger调试接口的流程! 1.首先我们创建一个MVC项目(VS2012): 2.然后在项目中的Controllers文件夹中添加API接口 ...

  10. HBase的简单介绍,寻址过程,读写过程

    HBase是列族数据库,主要由,表,行键,列族,列标识,值,时间戳 组成,         表   其中HBase 主要底层存储依赖与hdfs,可以在HDFS中看到每个表名都作为一个独立的目录结构   ...