最近想要用C++写个socket的服务器,用于日常的项目开发。
不过,我是新手,那就慢慢地学习一下吧。

首先,先写一段程序,用起来先。
感谢博文: Linux下 C++调用C 实现socket网络通讯编程 - 雕戈 - ITeye技术网站

Server

#include<iostream>
using namespace std;//head files of Linux
#include<netinet/in.h>
#include<unistd.h>   //for fork and read
#include<sys/types.h>   //for socket
#include<sys/socket.h>  //for socket
#include<string.h> // for bzero
#include<arpa/inet.h>void server()
{const unsigned short SERVERPORT = 53556;const int BACKLOG = 10; //10 个最大的连接数const int MAXSIZE = 1024;int sock, client_fd;sockaddr_in myAddr;sockaddr_in remoteAddr;sock = socket(AF_INET, SOCK_STREAM, 0);//create socketif( sock == -1){cerr<<"socket create fail!"<<endl;exit(1);}cout<<"sock :"<<sock<<endl;//bindmyAddr.sin_family = AF_INET;myAddr.sin_port = htons(SERVERPORT);myAddr.sin_addr.s_addr = INADDR_ANY;bzero( &(myAddr.sin_zero), 8);if(bind(sock, (sockaddr*)(&myAddr), sizeof(sockaddr)) ==-1 ){cerr<<"bind error!"<<endl;exit(1);}//listenif(listen(sock, BACKLOG) == -1){cerr<<"listen error"<<endl;exit(1);}while(true){unsigned int sin_size = sizeof(sockaddr_in);if( (client_fd = accept(sock, (sockaddr*)(&remoteAddr), &sin_size)) ==-1 ){cerr<<"accept error!"<<endl;continue;}cout<<"Received a connection from "<<static_cast<char*>(inet_ntoa(remoteAddr.sin_addr) )<<endl;//子线程if(!fork() ){int rval;char buf[MAXSIZE];if( (rval = read(client_fd, buf, MAXSIZE) ) <0){cout<<"Reading stream error!\n";continue;}cout<<buf<<endl;//向客户端发送信息const char* msg = "Hello, I am xiaojian. You are connected !";if( send(client_fd, const_cast<char*>(msg), strlen(msg), 0) == -1)cerr<<"send error!"<<endl;close(client_fd);exit(0);}}
}       int main()
{server();
}

Client

#include<iostream>
using namespace std;#include<string.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
void client()
{const unsigned short SERVERPORT = 53556;const int MAXSIZE = 1024;const char* SERVER_IP = "115.159.90.99";const char* DATA = "this is a client message ";int sock, recvBytes;char buf[MAXSIZE];
//    hostent *host;sockaddr_in serv_addr;if( (sock = socket(AF_INET, SOCK_STREAM, 0)) == -1){cerr<<"socket create fail!"<<endl;exit(1);}bzero( &serv_addr, sizeof(serv_addr) );serv_addr.sin_family =  AF_INET;serv_addr.sin_port = htons(SERVERPORT);serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);if( connect(sock, (sockaddr*)&serv_addr, sizeof(sockaddr)) == -1){cerr<<"connect error"<<endl;exit(1);}write(sock, const_cast<char*>(DATA), strlen(DATA) );if( (recvBytes = recv(sock, buf, MAXSIZE, 0)) == -1){cerr<<"recv error!"<<endl;exit(1);}buf[recvBytes] = '\0';cout<<buf<<endl;close(sock);
}int main()
{client();
}

代码比较容易理解,主要是各种 API 的理解和使用。

一些函数和结构

sockaddr_in

解释一下代码:
首先看到一个结构体:sockaddr_in,这是什么结构呢
sockaddr_in 在头文件in.h中声明,这个头文件在/usr/include/netinet/目录下,去一看究竟,可以找到它的声明:

/* Structure describing an Internet socket address.  */
struct sockaddr_in{__SOCKADDR_COMMON (sin_);in_port_t sin_port;         /* Port number.  */struct in_addr sin_addr;        /* Internet address.  *//* Pad to size of `struct sockaddr'.  */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];};

一个比较好的解释:sockaddr和sockaddr_in的区别 - The time is passing - ITeye技术网站
(其实我并不懂,所以暂时不解释)
但是这里要提到的几句代码:

    myAddr.sin_family = AF_INET;myAddr.sin_port = htons(SERVERPORT);myAddr.sin_addr.s_addr = INADDR_ANY;bzero( &(myAddr.sin_zero), 8);

其中 AF_INET 定义了协议族(TCP\UDP等)。

socket函数

函数名: socket(建立一个socket通信)
表头文件: #include<sys/types.h> #include<sys/socket.h>
定义函数: int socket(int domain,int type,int protocol);
函数说明: socket()用来建立一个新的socket,也就是向系统注册,通知系统建立一通信端口。参数domain 指定使用何种的地址类型,完整的定义在/usr/include/bits/socket.h内。
返回值: 成功则返回socket处理代码,失败返回-1。

bind函数

函数名: bind(对socket定位)
表头文件: #include<sys/types.h> #include<sys/socket.h>
定义函数: int bind(int sockfd,struct sockaddr * my_addr,int addrlen);
函数说明: bind()用来设置给参数sockfd的socket一个名称。此名称由参数my_addr指向一sockaddr结构,对于不同的socket domain定义了一个通用的数据结构
返回值: 成功则返回0,失败返回-1,错误原因存于errno中。

listen函数

函数名: listen(等待连接)
表头文件: #include<sys/socket.h>
定义函数: int listen(int s,int backlog);
函数说明: listen()用来等待参数s 的socket连线。参数backlog指定同时能处理的最大连接要求,如果连接数目达此上限则client端将收到ECONNREFUSED的错误。Listen()并未开始接收连线,只是设置socket为listen模式,真正接收client端连线的是accept()。通常listen()会在socket(),bind()之后调用,接着才调用accept()。
返回值: 成功则返回0,失败返回-1,错误原因存于errno。
附加说明: listen()只适用SOCK_STREAM或SOCK_SEQPACKET的socket类型。如果socket为AF_INET则参数backlog 最大值可设至128。

accept函数

函数名: accept(接受socket连线)
表头文件: #include<sys/types.h> #include<sys/socket.h>
定义函数: int accept(int s,struct sockaddr * addr,int * addrlen);
函数说明: accept()用来接受参数s的socket连线。参数s的socket必需先经bind()、listen()函数处理过,当有连线进来时accept()会返回一个新的socket处理代码,往后的数据传送与读取就是经由新的socket处理,而原来参数s的socket能继续使用accept()来接受新的连线要求。连线成功时,参数addr所指的结构会被系统填入远程主机的地址数据,参数addrlen为scokaddr的结构长度。关于结构sockaddr的定义请参考bind()。
返回值: 成功则返回新的socket处理代码,失败返回-1,错误原因存于errno中。

send函数

函数名: send(经socket传送数据)
表头文件: #include<sys/types.h> #include<sys/socket.h>
定义函数: int send(int s,const void * msg,int len,unsigned int falgs);
函数说明: send()用来将数据由指定的socket 传给对方主机。参数s为已建立好连接的socket。参数msg指向欲连线的数据内容,参数len则为数据长度。参数flags一般设0。
返回值: 成功则返回实际传送出去的字符数,失败返回-1。错误原因存于errno

recv函数

函数名: recv(经socket接收数据)
表头文件: #include<sys/types.h> #include<sys/socket.h>
定义函数: int recv(int s,void *buf,int len,unsigned int flags);
函数说明: recv()用来接收远端主机经指定的socket传来的数据,并把数据存到由参数buf 指向的内存空间,参数len为可接收数据的最大长度。
返回值: 接收的实际长度

connect函数

函数名: connect(建立socket连线)
表头文件: #include<sys/types.h> #include<sys/socket.h>
定义函数: int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);
函数说明: connect()用来将参数sockfd 的socket 连至参数serv_addr 指定的网络地址。结构sockaddr请参考bind()。参数addrlen为sockaddr的结构长度。
返回值: 成功则返回0,失败返回-1,错误原因存于errno中。

其他函数

read : 由已打开的文件读取数据
write: 将数据写入已打开的文件内
htons:将16位主机字符顺序转换成网络字符顺序
bzero:将一段内存内容全清为零
inet_addr:将网络地址转成二进制的数字

函数可以在参考资料中的Linux 常用手册找到。
但为了代码的可兼容性,我个人的意见是,尽量少用依赖于平台的函数,多用标准库,这样代码可以轻易移植到其他支持 C++ 编译的平台。

参考资料:
Linux下 C++调用C 实现socket网络通讯编程 - 雕戈 - ITeye技术网站
sockaddr和sockaddr_in的区别 - The time is passing - ITeye技术网站
简单理解Socket - Samaritans - 博客园
Linux 常用C函数(中文版)

C++服务器(一):了解Linux下socket编程相关推荐

  1. Linux下Socket编程

    Linux下Socket编程    网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符.Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的S ...

  2. 一文了解linux下socket编程

    一文了解linux下socket编程 文章目录 一文了解linux下socket编程 1 网络编程的相关简述 1.1 引言 1.2 Tcp和Udp简介 1.3 TCP三次握手和四次挥手 1.4 网络编 ...

  3. LINUX下Socket编程 函数格式详解

    你需要了解的一些系统调用: socket() bind() connect() listen() accept() send() recv() sendto() recvfrom() close() ...

  4. linux下socket编程读写函数

    linux下socket编程,实现服务器与客户端的通信之后,在同一个虚拟机上,打开两个shell,一个运行服务器程序,一个运行客户端程序,课相互发送数据. 如果使用的是recv接收函数,当关闭客户端或 ...

  5. [zz]Linux 下 socket 编程示例

    本示例为 Client/Server 结构,通过代码演示 Client 如何建立连接,并向远程端发送数据:Server 端如何侦听系统连接请求,接收请求并建立连接,进而获取客户端发来的数据.代码虽短, ...

  6. linux下socket编程中setsockopt的作用

    如题所示,在linux进行socket编程的时候,一般而言,socket,bind,listen三步曲之后,就开始接收客户端请求,然后实现收发数据. 如下所示的代码,是没有setsockopt的情况: ...

  7. linux下socket编程实现一个服务器连接多个客户端

    使用socekt通信一般步骤 1)服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接. 2)客户端:socker()建立套接字,连接(con ...

  8. linux socket 结构定义 send,Linux下Socket编程中用send发送结构体

    Linux网络通信 Linux下多客户端聊天软件 最近在开发一个Linux下的聊天软件,好久没有做C语言的开发了,感觉到很多东西已经生疏了,这下又碰到用Socket传递结构体的问题,google了一下 ...

  9. 【Linux】Linux 下socket 编程

    TCP/IP协议叫做传输控制/网际协议,又叫网络通信协议 TCP/IP虽然叫传输控制协议(TCP)和网际协议(IP),但是实际上是一组协议,包含ICMP, RIP, TELENET, FTP, SMT ...

最新文章

  1. python端午dragboat消消乐 美轮美奂的界面效果
  2. 猜数游戏python_Hello,Python!小鲸教你学Python(九)之文件操作
  3. 无需训练RNN或生成模型,我写了一个AI来讲故事
  4. frontpage 编辑html 乱码,在 FrontPage 2003 中编辑 PHP 及乱码问题
  5. php 协程怎么用,PHP yield 协程 生成器用法的了解
  6. 学会打败你的时间“窃贼”!!
  7. 【项目管理】接手一支技术团队,你会做些哪些事?
  8. html 调入网页,HTML 文件怎么从外部调入 HTML 模板(如头部,页尾这些公共的部分)?...
  9. Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4) dfs + 思维
  10. linux中统计java数量,linux 统计当前目录下文件数
  11. PyCharm配置django环境
  12. ExtJs五(ExtJs Mvc登录优化)
  13. c# linux 效率,c# – linux / mono上的HTTP性能
  14. 数据结构 6-0 图
  15. 【图像加密】基于matlab GUI+Logistic+Tent+Kent+Henon图像加密与解密【含Matlab源码 1745期】
  16. Linux 下制作虚拟软盘镜像
  17. VOIP Codec 三剑客之 ISAC/ILBC -- ISAC (1) 介绍
  18. 2022放假安排时间表(来自天才哥快速阅读)
  19. Verilator+gtkwave
  20. 简单处理Ubuntu无法联网的问题

热门文章

  1. 华栖云联合阿里云发布“云上电视台” 实现媒体云端采编播存管
  2. 基于Android的手机音乐播放器的设计
  3. 基于OpenCV做图像数据增强(平移、镜像、缩放、旋转、仿射)
  4. 13个坏习惯让IT工作者过度劳累
  5. Easyexcel·读取excel
  6. Android UnitTest
  7. 回文是指正读反读均相同的字符序列;如“abba”和“abdba”均是回文,但“good”不是回文。试写一个算法判定给定的字符序列是否是回文。(提示:将一半字符入栈)
  8. 什么是DDL和DML语句?
  9. html z-index不显示,CSS3关于z-index不生效问题的解决
  10. 无序数组中获取第k个最大数