linux socket编程步骤,Linux下TCP/IP socket编程(C++)

一、基于TCP的c/s交互流程

48829c347d56

C/S

48829c347d56

C/S

服务器端:

socket() → bind() → listen() → accept() → recv()/read() ↔ send()/write() → close()

创建socket → 绑定socket和端口号 → 监听端口号 → 接收来自客户端的连接请求 → 从socket中读取字符 → 关闭socket

客户端:

socket() → connect() → send()/write() ↔ recv()/read() → close()

创建socket → 连接指定服务器的IP/端口号 → 向socket中写入信息 → 关闭socket

二、C++代码实现

1、server.cpp

按照该实现,服务器每次只能服务一个客户端。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "cs.h"

#include "ErrCode.h"

using namespace std;

#define PORT 9977

#define MSG_SIZE 4096

#define MAX_LINE 20

int server() {

char cMsg[MSG_SIZE], sMsg[MSG_SIZE];

struct sockaddr_in serverAddr; // 一个将来与套接字绑定的结构体

memset(&serverAddr, 0, sizeof(serverAddr));

serverAddr.sin_port = (PORT); // 从服务器的PORT端口接收客户端信息

serverAddr.sin_family = AF_INET; // 协议簇,AF_INET表示TCP/IP协议

serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 指定接收的信息来自于某个IP,这里随意

int fd_skt = socket(AF_INET, SOCK_STREAM, 0); // (1)socket函数新建套接字fd_skt

if (fd_skt < 0) {

perror("server socket err");

return SERVER_SOCKET_ERR;

}

if (bind(fd_skt, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0 ) { // (2)bind绑定套接字与serverAddr

perror("server bind err");

return SERVER_BIND_ERR;

}

if (listen(fd_skt, MAX_LINE) < 0) { // (3)listen监听套接字fd_skt

perror("server listen err");

return SERVER_LISTEN_ERR;

}

cout << "Listening..." << endl;

while(1) {

memset(cMsg, 0, sizeof(cMsg));

memset(sMsg, 0, sizeof(sMsg));

struct sockaddr_in clientAddr;

socklen_t length = sizeof(clientAddr);

int fd_client = accept(fd_skt, (struct sockaddr*)&clientAddr, &length);

// (4)accept接收连接请求:程序在此阻塞直至产生第一次握手

// 接收到的信息存于第二第三个参数中

// 返回值是新的文件描述符,用于后续read和write调用

if (fd_client < 0) {

perror("server accept err");

return SERVER_ACCEPT_ERR;

}

cout << "server: got connection from " << clientAddr.sin_addr.s_addr

<< ", port " << PORT

<< ", socket" << fd_client << endl;

while(1) {

int cLen = recv(fd_client, cMsg, sizeof(cMsg), 0); // (5)read将接收到的客户端消息存在cMsg中

if (cLen <= 0) {

perror("server recv err");

return SERVER_RECV_ERR;

}

cMsg[cLen] = '\0';

cout << "Receive message form : " << cMsg << endl;

cin.ignore(1024,'\n'); // 去除上一个cin残留在缓冲区的\n

cin.getline(sMsg, sizeof(sMsg)); // 不用cin,因为不能含空格

if(strcmp(sMsg, "quit\n") == 0){

break; // 结束对当前客户端的服务

}

if(send(fd_client, sMsg, strlen(sMsg), 0) <= 0) { // (6)send将服务器的消息发给客户端

perror("server send err");

return SERVER_SEND_ERR;

}

// recv和send的返回值:

// >0表示成功,返回实际发送或接受的字节数

// =0表示超时,对方主动关闭了连接过程

// <0出错

cout << "Send message to : " << sMsg << endl;

}

close(fd_client);

cout << "当前客户端已结束通信,是否继续等待其他客户端?(1 - 是, 0 - 否)" << endl;

bool isContinue = false;

cin >> isContinue;

if (!isContinue) {

break;

}

}

close(fd_skt);

return SUCCESS;

}

2、client.cpp

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "cs.h"

#include "ErrCode.h"

using namespace std;

#define PORT 9977

#define MAX_LINE 20

#define MSG_SIZE 4096

#define DEFAULT_SERVER "127.0.0.1"

int client() {

char cMsg[MSG_SIZE], sMsg[MSG_SIZE];

struct sockaddr_in serverAddr; // 一个将来与套接字绑定的结构体

memset(&serverAddr, 0, sizeof(serverAddr));

serverAddr.sin_port = (PORT); // 从客户端的PORT端口接收服务器信息

serverAddr.sin_family = AF_INET; // 协议簇,AF_INET表示TCP/IP协议

cout << "Please input the server address: (输入1连接默认服务器)" << endl;

char sAddr[20];

cin >> sAddr;

if (strcmp(sAddr, "1") == 0) {

if(inet_pton(AF_INET, DEFAULT_SERVER, (void *)&serverAddr.sin_addr) <= 0) {

perror("client inet_pton err");

return CLIENT_INETPTON_ERR;

}

}

else {

if(inet_pton(AF_INET, DEFAULT_SERVER, (void *)&serverAddr.sin_addr) <= 0) {

perror("client inet_pton err");

return CLIENT_INETPTON_ERR;

}

}

int fd_skt = socket(AF_INET, SOCK_STREAM, 0); // (1)socket函数新建套接字fd_skt

if (fd_skt < 0) {

perror("client socket err");

return CLIENT_SOCKET_ERR;

}

if (connect(fd_skt, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { //(2)connect向服务器发起连接请求

perror("client connect err");

return CLIENT_CONNECT_ERR;

}

cout << "Connect Success! \nBegin to chat..." << endl;

while(1) {

memset(cMsg, 0, sizeof(cMsg));

memset(sMsg, 0, sizeof(sMsg));

cin.ignore(1024,'\n'); // 去除上一个cin残留在缓冲区的\n

cin.getline(cMsg, sizeof(cMsg)); // 不用cin,因为不能含空格

if(strcmp(cMsg, "quit\n") == 0){

break;

}

if(send(fd_skt, cMsg, strlen(cMsg), 0) < 0) { // (3)send,客户端向服务端发消息

perror("client send err");

return CLIENT_SEND_ERR;

}

cout << "Send message to : " << cMsg << endl;

int sLen = recv(fd_skt, sMsg, sizeof(sMsg),0); // (4) recv,接收服务器发来的消息

if(sLen <= 0) {

perror("client recv err");

return CLIENT_RECV_ERR;

}

sMsg[sLen] = '\0';

cout << "Receive message form : " << sMsg << endl;

}

close(fd_skt);

}

3、main.cpp

#include

#include "cs.h"

using namespace std;

int main() {

cout << "————————【chat start】————————" << endl;

while(1) {

cout << "Client or Server?" << endl;

char cs;

cin >> cs;

if (cs == 's') {

if(server() != 0){

break;

}

}

else if (cs == 'c') {

if(client() != 0){

break;

}

}

else {

cout << "err input" << endl;

}

}

cout << "————————【chat end】————————" << endl;

return 0;

}

4、ErrCode.h

#define SUCCESS 0

#define SERVER_SOCKET_ERR 1000

#define SERVER_BIND_ERR 1001

#define SERVER_LISTEN_ERR 1002

#define SERVER_ACCEPT_ERR 1003

#define SERVER_RECV_ERR 1004

#define SERVER_SEND_ERR 1005

#define CLIENT_INETPTON_ERR 1010

#define CLIENT_SOCKET_ERR 1011

#define CLIENT_CONNECT_ERR 1012

#define CLIENT_SEND_ERR 1013

#define CLIENT_RECV_ERR 1014

5、cs.h

#include

int server();

int client();

3、运行效果

48829c347d56

client

48829c347d56

server

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值