ソケットプログラミング__tcp
TCP:伝送制御プロトコル:接続指向、信頼性の高い伝送、指向バイトストリーム、シナリオデータのセキュリティは、リアルタイムのシーンよりも大きい - ファイル転送。(上位層は送信データサイズに限定されるものではありません)
UDPネットワーク通信プログラムの流れ:
ソケットインタフェースの説明:
1.ソケットを作成します。
int socket(int domain, int type, int protocol)
ドメイン:----異なるネットワークアドレスフィールドアドレス構造AF-INET(IPv4のアドレスフィールド)
タイプ:ソケットタイプ-ストリームソケット/データグラムソケット
ストリームソケット:整然とした信頼性の高い、双方向、接続ベースのストリーミングSOCK_STREAMバイト
のデータグラムソケット:コネクション信頼性の低い伝送SOCK_DGRAMの最大長がある
プロトコルは:異なるソケットタイプ0で使用されるプロトコル----デフォルトのプロトコル:ストリームソケットTCP /データグラムソケットデフォルトUDP
IPPROTO_TCPは行く- TCPプロトコルIPPROTO_UDP - UDPプロトコルの
戻り値は:操作ハンドルソケットファイルディスクリプタを返します-----
2.アドレスバインディング
int bind(int sockfd, struct sockaddr* addr, socklen_t len);
数sockfd:ソケット作成操作ハンドルが返されます。
ADDR:バインドへのアドレス構造の情報を
LEN:アドレス情報の長さ
戻り値:戻り0成功した場合、失敗すると-1。
3.サーバーがリスニングを開始
int listen(int sockfd, int backlog);
バックログ:意思決定と同時に、サーバは、クライアントの接続要求を受け入れることができますが、サーバはパラメータを受け入れることができますどのように多くのクライアントを決定することはできません。
キューパラメータ保留中の接続は、クライアントが受け入れることができますどのくらいを示していることができますがあります。キューが満杯になると、後続の要求は破棄されます。
新しいソケットに操作ハンドルを取得します。4.
int accept(int sockfd, struct sockaddr* addr, socklen_t *len);
数sockfd:リスニングソケット-あなたがキュー保留中のソケットを取得したい
ADDRを:addrで、指定されたクライアントの通信に、顧客情報へのアクセスをこのソケットをソケットを取得する
アドレス情報が欲しかった指定:lenは実際のアドレス長の長さ戻ります
戻り値:戻りが正常に新しいソケット記述子を取得し、それ以外の戻り1;
受信したデータ
ssize_t recv(int sockfd, char *buf, int len, int flag);
数sockfd:ソケット操作ハンドル
BUF:ソケットを受信するためにバッファカーネルから受信したデータを格納するための第1のアドレスバッファは、ユーザモードBUFバッファにデータを削除します。
LEN:ユーザーがなく、より多くのバッファbufの長さよりも、読みたいデータの長さ。
フラグに:0 -デフォルトのブロック操作-バッファがノンブロッキングMSG_DONTWAIT-を待っているデータがない場合
戻り値:データの実際の数の成功読み取りバイトを返し、切断リターンを0、それ以外の戻り1;
6.データ伝送
ssize_t send(int sockfd, char* data, int len, int flag);
ソケットハンドル操作を、送信データがバッファカーネルソケットの送信にデータをコピーすることである:数sockfd
データ:に送信する最初のデータのアドレス
、送信すべきデータの長さ:int_len
のフラグ:0デフォルトのオプションに現在の動作を示すパラメータ操作MSG_DONTWAITブロック-非ブロックに設定し
、データを送信する場合は、ソケットの送信バッファは、0を待っているデフォルトのブロックがいっぱいです。MSG_DONTWAITはすぐにエラーを返します。
戻り値:実際に正常に送信データのバイト長を返し、失敗したリターンが-1;接続が切断された場合に例外がトリガされ、プロセスが終了します。
7.閉じるソケット
int close(int fd);
8.クライアントは、サーバーへの接続要求を送信します
int connect(int sockfd, int sockaddr* addr, socklen_t len);
数sockfd:クライアントソケット-まだアドレスをバインドされていない場合、オペレーティングシステムが適切なソースアドレスバインディングを選択します
ADDRを:サーバアドレス情報
lenは、アドレス情報の長さを。
9.コード
1.tcpsocket.hpp
#pragma once
#include <cstdio>
#include <string>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define BACKLOG 10
#define CHECK_RET(q) if((q)==false){return -1;}
class TcpSocket
{
public:
TcpSocket():_sockfd(-1){
}
//创建套接字
bool Socket() {
_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(_sockfd < 0) {
perror("socket error");
return false;
}
return true;
}
void Addr(struct sockaddr_in *addr, const std::string &ip, const uint16_t port) {
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
inet_pton(AF_INET, ip.c_str(), &(addr->sin_addr.s_addr));
}
bool Bind(const std::string &ip, const uint16_t port) {
struct sockaddr_in addr;
Addr(&addr, ip, port);
socklen_t len = sizeof(struct sockaddr_in);
int ret = bind(_sockfd, (struct sockaddr*)&addr, len);
if(ret < 0)
{
perror("bind error");
return false;
}
return true;
}
bool Listen(int backlog = BACKLOG){
int ret = listen(_sockfd, backlog);
if(ret < 0){
perror("listen error");
return false;
}
return true;
}
bool Connect(const std::string &ip, const uint16_t port) {
struct sockaddr_in addr;
Addr(&addr, ip, port);
socklen_t len = sizeof(struct sockaddr_in);
int ret = connect(_sockfd, (struct sockaddr*)&addr, len);
if(ret < 0) {
perror("connet error");
return false;
}
return true;
}
bool Accept(TcpSocket *sock, std::string *ip = NULL, uint16_t *port = NULL){
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
int clisockfd = accept(_sockfd, (struct sockaddr*)&addr, &len);
if(clisockfd < 0) {
perror("accept error");
return false;
}
sock->_sockfd = clisockfd;
if(ip != NULL) {
*ip = inet_ntoa(addr.sin_addr);
}
if(port != NULL) {
*port = ntohs(addr.sin_port);
}
return true;
}
bool Send(const std::string &data) {
int ret = send(_sockfd, data.c_str(), data.size(), 0);
if(ret < 0) {
perror("send error");
return false;
}
return true;
}
bool Recv(std::string *buf) {
char tmp[4096] = {0};
int ret = recv(_sockfd, tmp, 4096, 0);
if(ret < 0) {
perror("recv error");
return false;
}else if(ret == 0){
printf("connection break\n");
return false;
}
buf->assign(tmp, ret);
return true;
}
bool Close() {
close(_sockfd);
_sockfd = -1;
}
private:
int _sockfd;
};
2.tcp_cli.cpp
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include "tcpSocket.hpp"
int main(int argc, char *argv[])
{
if(argc != 3) {
printf("em:./tcp_cli 172.17.0.1 9010 ---服务绑定的地址\n");
return -1;
}
std::string ip = argv[1];
uint16_t port = atoi(argv[2]);
TcpSocket cli_sock;
CHECK_RET(cli_sock.Socket());
CHECK_RET(cli_sock.Connect(ip, port));
while(1) {
printf("client say:");
fflush(stdout);
std::string buf;
std::cin >> buf;
CHECK_RET(cli_sock.Send(buf));
buf.clear();
CHECK_RET(cli_sock.Recv(&buf));
printf("server say: %s\n", buf.c_str());
}
cli_sock.Close();
return 0;
}
3.tcp_srv.cpp
#include<iostream>
#include<stdlib.h>
#include "tcpSocket.hpp"
int main(int argc, char *argv[])
{
if(argc != 3) {
printf("em: ./tcp_srv 172.17.0.1 9010\n");
return -1;
}
std::string ip = argv[1];
uint16_t port = atoi(argv[2]);
TcpSocket lst_sock;
CHECK_RET(lst_sock.Socket());
CHECK_RET(lst_sock.Bind(ip, port));
CHECK_RET(lst_sock.Listen());
while(1) {
TcpSocket cli_sock;
std::string cli_ip;
uint16_t cli_port;
bool ret = lst_sock.Accept(&cli_sock, &cli_ip, &cli_port);
if(ret == false) {
continue;
}
std::string buf;
if(cli_sock.Recv(&buf) == false) {
cli_sock.Close();
continue;
}
printf("client:[%s:%d] say:%s\n", &cli_ip[0], cli_port, &buf[0]);
std::cout << "server say;";
fflush(stdout);
buf.clear();
std::cin >> buf;
if(cli_sock.Send(buf) == false){
cli_sock.Close();
continue;
}
}
lst_sock.Close();
return 0;
}