实验平台

linux

实验内容

编写TCP服务器和客户端程序,程序运行时服务器等待客户端连接。一旦连接成功,服务器显示客户端的IP地址和端口号,并向客户端发送字符串

实验原理

TCP是面向连接的通信,其主要实现过程如下:

我们将服务器代码分为两部分。

1. init_tcp_server() tcp服务器的初始化

2. main() 实现读写数据

这样做的好处是main函数不必写的特别冗长,利于维护。从框架上来说,服务器的初始化也与读、写无关。

tcp服务器的初始化----init_tcp_server()

1. 创建socket

sockfd = socket(AF_INET, SOCK_STREAM, ); //AF_INT:ipv4, SOCK_STREAM:tcp协议

2. 设置socket  当然这一步可以省略

int32_t opt = ;
ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

详细说明:

3. 绑定(bind函数)

将socket和地址(包括ip,port)绑定。需要定义一个结构体地址,以便于将port的主机字节序转化成网络字节序

struct sockaddr_in serveraddr;    //地址结构体

bind函数

bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))

4. listen监听,将接收到的客户端放入队列

 listen(sockfd,)  //第二个参数是队列长度

5. 调用accept函数,从队列获取请求,返回socket描述符,如果没有请求(没有客户端连接),将会阻塞,直到获取请求

int fd=accept(sockfd, (struct sockaddr*)&clientaddr, &clientaddr_len);

至此服务器初始化完成,返回成功连接的套接字fd。

服务器端代码如下:tcpserver.c

#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h> #define PORT 1234
#define BACKLOG 10
#define BUFFER_SIZE 100 /**
* @brief 初始化tcp服务器
* @param[in] listenfd 监听套接字
* @return -1 - 失败, socket 文件句柄 - 成功
*/
int32_t init_tcp_server(int32_t listenfd)
{
struct sockaddr_in server;
struct sockaddr_in client; int32_t connectfd = ;
int32_t addrlen;
int32_t ret = ;
addrlen = sizeof(client); /**< 创建一个tcp套接字 */
listenfd = socket(AF_INET, SOCK_STREAM, );
if (listenfd == -)
{
perror("create socket failed!\n");
exit();
} /**< 设置一个tcp套接字 */
int32_t opt = ;
ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if (ret < )
{
perror("set socket failed!\n");
exit();
} /**< 设置服务器监听所有的IP地址 */
bzero(&server, sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_port = htons(PORT); /**< 主机字节序转化成网络字节序 */
server.sin_addr.s_addr = htonl(INADDR_ANY); /**< 与服务器进行绑定 */
if (bind(listenfd, (struct sockaddr *)&server, sizeof(server)) == -)
{
perror("bind error");
exit();
} /**< 监听 */
if (listen(listenfd, BACKLOG) == -)
{
perror("listen error");
exit();
} /**< 等待客户端连接,如果没有,一直阻塞 */
if ((connectfd = accept(listenfd, (struct sockaddr *)&client, &addrlen)) == -)
{
perror("accept error");
close(listenfd);
close(connectfd);
exit();
}
printf("You got a connection from client's ip is %s, port is %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); return connectfd;
} int main()
{
int32_t listenfd = ;
int32_t connectfd = ;
char buf[BUFFER_SIZE] = "Welcome to my server"; connectfd = init_tcp_server(listenfd); send(connectfd, buf, BUFFER_SIZE, ); /**< 发送信息到客户端 */
close(connectfd);
close(listenfd);
}

客户端

同样,将客户端代码分成两部分:

1. init_tcp_client() tcp客户端的初始化

2. main() 实现读写数据

客户端的初始化较为简单,如上图,只要实现socket和connect函数即可。但是我们希望可以手动输入客户端连接的IP地址,便于以后扩展,因此需要给客户端初始化传入一个参数。例如,输入:

./tcpclient 127.0.0.1

客户端代码如下:tcpclient.c

#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h> #define PORT 1234
#define BUFFER_SIZE 100 int32_t init_tcp_client(char *ipaddr)
{
int sockfd = ;
struct sockaddr_in server; if ((sockfd = socket(AF_INET, SOCK_STREAM, )) == -)
{
perror("create socket failed!\n");
exit();
} bzero(&server, sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
inet_pton(AF_INET, ipaddr, &server.sin_addr.s_addr); /**< 点分十进制转换成二进制的网络字节序 */ if (connect(sockfd, (struct sockaddr *)&server, sizeof(server)) == -)
{
perror("connect error");
exit();
} return sockfd;
} int32_t main(int argc, char*argv[])
{
int32_t sockfd, num;
char buf[BUFFER_SIZE];
if (argc != )
{
printf("Usage:%s <IP Address>\n",argv[]);
exit();
}
sockfd = init_tcp_client(argv[]); if ((num = recv(sockfd, buf, BUFFER_SIZE, )) == -)
{
perror("recv error");
exit();
} buf[num - ] = '\0';
printf("Server Message: %s\n", buf);
close(sockfd); return ;
}

Makefile文件如下:

all:server client

server:tcpserver.c
gcc tcpserver.c -o server client:tcpclient.c
gcc tcpclient.c -o client clean:
rm -rf server client

实验结果如下:

基于TCP的客户端和服务器端的代码设计的更多相关文章

  1. 基于UDP的客户端和服务器端的代码设计

    实验平台 linux 实验内容 编写UDP服务器和客户端程序,客户端发送消息,服务器接收消息,并打印客户端的IP地址和端口号. 实验原理 UDP是无需连接的通信,其主要实现过程如下: 同样,我们可以按 ...

  2. 基于TCP的客户端、服务器端socket编程

    一.实验目的 理解tcp传输客户端服务器端通信流程 二.实验平台 MAC OS 三.实验内容 编写TCP服务器套接字程序,程序运行时服务器等待客户的连接,一旦连接成功,则显示客户的IP地址.端口号,并 ...

  3. UDP广播的客户端和服务器端的代码设计

    实验环境 linux 注意: 使用UDP广播,是客户端发送广播消息,服务器端接收消息.实际上是客户端探测局域网中可用服务器的一种手段.客户端发送,服务器端接收,千万不能弄混淆!!! 为了避免混淆,本文 ...

  4. 使用CXF开发WebService程序的总结(四):基于bean的客户端和服务端代码的编写

    1. 在原服务端项目 ws_server中添加两个bean 1.1 添加两个类  User 和 Clazz   package com.lonely.pojo; public class User { ...

  5. 实验09——java基于TCP实现客户端与服务端通信

    TCP通信         需要先创建连接 - 并且在创建连接的过程中 需要经过三次握手        底层通过 流 发送数据 数据没有大小限制        可靠的传输机制 - 丢包重发 包的顺序的 ...

  6. C/S模型:TCP,UDP构建客户端和服务器端(BIO实现

    Java中提供了socket编程来构建客户端和服务器端 TCP构建服务器端的步骤:(1)bind:绑定端口号(2)listen:监听客户端的连接请求(3)accept:返回和客户端连接的实例(4)re ...

  7. 【TCP/IP网络编程】:04基于TCP的服务器端/客户端

    摘要:结合前面所讲述的知识,本篇文章主要介绍了简单服务器端和客户端实现的框架流程及相关函数接口. 理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP套接字和UDP套接字(本 ...

  8. C/C++网络编程5——实现基于TCP的服务器端/客户端2

    三次握手过程详解: 1:客户端的协议栈向服务器端发送SYN包,并告诉服务器端当前放送序号为j,客户端进入SYNC_SEND状态. 2:服务器端的协议栈收到这个包以后,和客户端进行ACK应答,应答值为j ...

  9. 基于TCP的安卓客户端开发

    一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户 ...

随机推荐

  1. ThinkPHP3.1.2 使用cli命令行模式运行

    ThinkPHP3.1.2 使用cli命令行模式运行 标签(空格分隔): php 前言 thinkphp3.1.2 需要使用cli方法运行脚本 折腾了一天才搞定 3.1.2的版本真的很古老 解决 增加 ...

  2. Java第十七天,Set接口

    Set接口 1.特点 (1)不包含重复元素. (2)没有索引. (3)继承自Collection接口,所以Collection接口中的所有方法都适用于Set接口. 2.解析 (1)为什么不能包含重复元 ...

  3. json文件操作

    1.把字典或list转换成字符串方法 json.dumps() 2.把字符串转换成字典方法 json.loads() 3.indent 存储文件时每行加缩进数 4.ensere_asci 文件中有中文 ...

  4. 【Selenium03篇】python+selenium实现Web自动化:元素三类等待,多窗口切换,警告框处理,下拉框选择

    一.前言 最近问我自动化的人确实有点多,个人突发奇想:想从0开始讲解python+selenium实现Web自动化测试,请关注博客持续更新! 这是python+selenium实现Web自动化第三篇博 ...

  5. 带你五分钟了解python的函数式编程与闭包

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:梁唐 PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行 ...

  6. 接口测试中实际发生的几个问题——python中token传递

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:AFKplayer PS:如有需要Python学习资料的小伙伴可以加点 ...

  7. 杭电1080 J - Human Gene Functions

    题目大意: 两个字符串,可以再中间任何插入空格,然后让这两个串匹配,字符与字符之间的匹配有各自的分数,求最大分数 最长公共子序列模型. dp[i][j]表示当考虑吧串1的第i个字符和串2的第j个字符时 ...

  8. adb命令查看手机应用内存使用情况

    adb shell回车 一.procrank VSS >= RSS >= PSS >= USSVSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)是单个 ...

  9. 使用dynamic 和MEF实现轻量级的 AOP 组件 (1)

    转载https://www.cnblogs.com/niceWk/archive/2010/07/19/1780843.html AOP魔法 今天你AOP了吗?谈到AOP,总有一种神秘的感觉,人类对于 ...

  10. Mac下打开 kvm

    mac 下打开 kvm ,需要装这个 https://www.xquartz.org/