教你如何编写TCP协议的客户端/服务器程序。 (tcp 服务器客户端程序)

教你如何编写TCP协议的客户端/服务器程序

TCP协议是网络编程中较为常见的协议之一,客户端/服务器程序也是开发中经常需要涉及到的应用场景。在本文中,将会详细介绍如何编写TCP协议的客户端/服务器程序,让读者能够掌握TCP协议的基本原理,以及如何使用C语言实现客户端/服务器程序。

一、TCP协议简介

TCP(Tranission Control Protocol,传输控制协议)是一个可靠的、面向连接的、基于流的传输层通信协议。它是IP协议族中的一员,主要用于互联网中数据的传输。TCP协议通过三次握手建立连接,可以提供完整的数据传输保证,同时也支持流量控制和拥塞控制,使得数据传输更加可靠和高效。

二、客户端/服务器程序设计

客户端/服务器程序是指一种系统架构,该架构中客户端与服务器之间通过网络通信来完成数据交互。在TCP协议中,客户端和服务器之间需要建立连接,才能进行通信。我们可以将服务器端理解为提供服务的主机,而客户端则是请求服务的主机。

在进行客户端/服务器程序设计时,我们需要了解请求方和响应方之间的通信流程。客户端向服务器发起连接请求,服务器收到请求后应做出响应,双方建立连接;之后,客户端向服务器发送请求,服务器接收到请求后进行相关处理,并返回处理结果给客户端。通信结束后,双方需要关闭连接。

三、实现TCP协议的客户端/服务器程序

在C语言中,我们可以使用socket和select函数来实现TCP协议的客户端/服务器程序。

1. 服务器端程序实现

服务器端程序需要完成以下几个步骤:

1)创建socket:使用socket函数创建套接字,该函数返回套接字文件描述符。

int socket(int domn, int type, int protocol);

2)绑定端口:使用bind函数将套接字绑定到一个端口上。

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

3)监听连接请求:使用listen函数监听连接请求。

int listen(int sockfd, int backlog);

4)接收连接请求:使用accept函数接收客户端的连接请求,并返回套接字文件描述符。

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

5)数据交互:通过读写套接字实现与客户端之间的数据交互。

示例代码如下:

#include

#include

#include

#include

#include

#include

#include

const int MAXLINE = 4096;

const int PORT = 9999;

const int MAXCONN = 100;

int mn() {

//1. 创建socket

int listenfd, connfd;

struct sockaddr_in servaddr, clientaddr;

char buff[MAXLINE];

listenfd = socket(AF_INET, SOCK_STREAM, 0);

if (listenfd == -1) {

perror(“socket error”);

exit(1);

}

printf(“socket ok\n”);

//2. 绑定端口

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(PORT);

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {

perror(“bind error”);

exit(1);

}

printf(“bind ok\n”);

//3. 监听连接请求

if (listen(listenfd, MAXCONN) == -1) {

perror(“listen error”);

exit(1);

}

printf(“listen ok\n”);

//4. 接收连接请求

while (1) {

socklen_t clilen = sizeof(clientaddr);

connfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clilen);

if (connfd == -1) {

perror(“accept error”);

exit(1);

}

printf(“accept ok\n”);

//5. 数据交互

int n;

while ((n = read(connfd, buff, MAXLINE)) > 0) {

buff[n] = ‘\0’;

printf(“recv: %s”, buff);

write(connfd, buff, strlen(buff)+1);

}

//6. 关闭连接

close(connfd);

printf(“close ok\n”);

}

return 0;

}

2. 客户端程序实现

客户端程序需要完成以下几个步骤:

1)创建socket:使用socket函数创建套接字,该函数返回套接字文件描述符。

int socket(int domn, int type, int protocol);

2)连接服务器:使用connect函数连接指定的服务器。

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

3)数据交互:通过读写套接字实现与服务器之间的数据交互。

4)关闭连接:使用close函数关闭连接。

示例代码如下:

#include

#include

#include

#include

#include

#include

#include

#include

const int MAXLINE = 4096;

const int PORT = 9999;

int mn(int argc, char **argv) {

if (argc != 2) {

printf(“usage: ./client \n”);

}

//1. 创建socket

int sockfd;

struct sockaddr_in servaddr;

char buff[MAXLINE];

sockfd = socket(AF_INET, SOCK_STREAM, 0);

if (sockfd == -1) {

perror(“socket error”);

exit(1);

}

printf(“socket ok\n”);

//2. 连接服务器

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(PORT);

if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) == -1) {

perror(“inet_pton error”);

exit(1);

}

if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {

perror(“connect error”);

exit(1);

}

printf(“connect ok\n”);

//3. 数据交互

int n;

while (fgets(buff, MAXLINE, stdin) != NULL) {

if (write(sockfd, buff, strlen(buff)+1) == -1) {

perror(“write error”);

exit(1);

}

if ((n = read(sockfd, buff, MAXLINE)) > 0) {

buff[n] = ‘\0’;

printf(“recv: %s”, buff);

}

}

//4. 关闭连接

close(sockfd);

printf(“close ok\n”);

return 0;

}

四、

相关问题拓展阅读:

C#中TCP进行同步套接字编程,服务器和客户端的工作流程(需要代码和图)

s端:建立套接字,晌乱绑定端口,监听,发送及接收;

c端丛早:建立套接字,基于端口连接宴郑档,发送及接收。

代码来了,。。

服务器:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Net.Sockets;

using System.Net;

using System.Reflection;

using System.Diagnostics;

using System.Text.RegularExpressions;

namespace msgServer

{

public partial class frmServer : Form

{

private Socket socket;

private IPAddress myIP;

private IPEndPoint endPoint;

private int point;

private Socket clientSocket;

private Assembly ass = null;

private System.IO.Stream stream = null;

private System.Media.SoundPlayer pl;

private string txt;

private byte bs = new byte;

public frmServer()

{

InitializeComponent();

ass = Assembly.GetExecutingAssembly();

stream = ass.GetManifestResourceStream(“msgServer.msg.wav”);

pl = new System.Media.SoundPlayer(stream);

}

//字体选择

private void btnFont_Click(object sender, EventArgs e)

{

FontDialog font = new FontDialog();

font.ShowEffects = true;

font.ShowColor = true;

font.MinSize = 12;

font.Font = new Font(“楷体_GB2312”, 18, FontStyle.Bold);

font.Color = Color.Blue;

if (font.ShowDialog() == DialogResult.OK)

{

rtxtSend.Font = font.Font;

rtxtSend.ForeColor = font.Color;

}

}

//开始监听

private void btnStart_Click(object sender, EventArgs e)

{

System.Threading.Thread th1 = new System.Threading.Thread(ToConnect);

th1.Start();

}

//去连接

private void ToConnect()

{

try

{

myIP = IPAddress.Parse(txtIP.Text.Trim());//IP

point = Convert.ToInt32(txtPoint.Text.Trim());//Point

endPoint = new IPEndPoint(myIP, point); //终端

socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

socket.Bind(endPoint);//绑定

socket.Listen(3); //最多3人同时连接

lblStatus.Text = “服务器已经运行…”;

clientSocket = socket.Accept();//等待接受

//连接上时

if (clientSocket.Connected)

{

lblStatus.Text = “已经建立连接.”;

while (true)

{

try

{

clientSocket.Receive(bs, bs.Length, 0);

pl.Play();

rtxtMsg.AppendText(System.Text.Encoding.Unicode.GetString(bs));

}

catch { lblStatus.Text = “连接已经断开.”; }

}

}

}

catch { txtIP.Focus(); txtIP.SelectAll(); MessageBox.Show(“IP error OR Point error”); }

}

//停止监听

private void btnStop_Click(object sender, EventArgs e)

{

try

{

socket.Close(3);

lblStatus.Text = “监听已经停止.”;

}

catch

{

lblStatus.Text = “目前未建立连接.”;

}

}

private void frmServer_KeyPress(object sender, KeyPressEventArgs e)

{

}

private void frmServer_KeyDown(object sender, KeyEventArgs e)

{

if ((e.Control && e.KeyCode == Keys.Enter) || (e.Alt && e.KeyCode == Keys.S))

{

btnSend.PerformClick();//单击发送

}

}

//发送消息

private void btnSend_Click(object sender, EventArgs e)

{

if (rtxtSend.Text.Trim() == “”)

return;

else if (rtxtSend.Text.Trim().ToLower() == “clear()”)

{

rtxtMsg.Clear();

rtxtSend.Text = “”;

return;

}

else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @”^++$”))

{

string str = rtxtSend.Text.ToLower();

int size = Convert.ToInt32(str.Substring(str.LastIndexOf(‘(‘) + 1,

str.IndexOf(‘)’) – str.LastIndexOf(‘(‘) – 1));

rtxtMsg.Font = new Font(“宋体”, size,FontStyle.Bold);

return;

}

else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @”^++$”))

{

string str = rtxtSend.Text.ToLower();

string size = str.Substring(str.LastIndexOf(‘(‘) + 1,str.IndexOf(‘)’) – str.LastIndexOf(‘(‘) – 1);

if (Convert.ToInt32(size) > rtxtMsg.Text.Length)

return;

}

else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @”^++$”))

{

string str = rtxtSend.Text.ToLower();

string size = str.Substring(str.LastIndexOf(‘(‘) + 1,str.IndexOf(‘)’) – str.LastIndexOf(‘(‘) – 1);

}

else if (rtxtSend.Text.Trim().ToLower() == “exit(0)”)

{

this.Close();

return;

}

try

{

byte bs = new byte;

string user = null;

if (txtUser.Text.Trim() == “在此输入你的名字” || txtUser.Text.Trim() == “”)

{

user = “我”;

bs = Encoding.Unicode.GetBytes(string.Format(“对方说:({0})\r\n{1}\r\n”,DateTime.Now.ToString(), rtxtSend.Text.Trim()));

}

else

{

bs = Encoding.Unicode.GetBytes(string.Format(“{0}说:({1})\r\n{2}\r\n”, txtUser.Text.Trim(),DateTime.Now.ToString(), rtxtSend.Text.Trim()));

user = txtUser.Text.Trim();

}

clientSocket.Send(bs, bs.Length, 0);//发送

txt = string.Format(“{0}说:({1})\r\n{2}\r\n”, user, DateTime.Now.ToString(),rtxtSend.Text.Trim());

int tempLen = rtxtMsg.Text.Length;

rtxtMsg.AppendText(txt);

rtxtMsg.Select(tempLen, txt.Length);

rtxtMsg.SelectionFont = new Font(“宋体”, 10);

rtxtMsg.SelectionColor = Color.Red;

rtxtSend.Clear();

}

catch { MessageBox.Show(“未建立连接,无法发送数据!”); }

}

//关闭Socket

private void frmServer_FormClosing(object sender, FormClosingEventArgs e)

{

try

{

//关闭连接

socket.Close(3);

}

catch (Exception) { }

finally

{

foreach (Process p in Process.GetProcesses())

{

if (p.ProcessName == Application.ProductName)

p.Kill();

}

}

}

private void frmServer_Load(object sender, EventArgs e)

{

foreach (Process p in Process.GetProcesses())

{

if (p.ProcessName == Application.ProductName)//已经启动

{

if (p.Id != Process.GetCurrentProcess().Id)//不是当前进程

{

p.Kill();

}

}

}

}

private void checkBox1_CheckedChanged(object sender, EventArgs e)

{

this.TopMost = checkBox1.Checked;

}

}

}

客户端:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Net;

using System.Net.Sockets;

using System.Diagnostics;

using System.Text.RegularExpressions;

namespace gClient

{

public partial class frmClient : Form

{

private IPAddress IP;//ip

private EndPoint endpoint;//point

private Socket socket;//socket

private System.IO.Stream stream = null;

private System.Reflection.Assembly ass = null;

private System.Media.SoundPlayer pl = null;

private string txt;

private byte bs = new byte;

public frmClient()

{

InitializeComponent();

ass = System.Reflection.Assembly.GetExecutingAssembly();

stream = ass.GetManifestResourceStream(“gClient.msg.wav”);

pl = new System.Media.SoundPlayer(stream);

}

//请求连接

private void btnRequestConnect_Click(object sender, EventArgs e)

{

System.Threading.Thread th = new System.Threading.Thread(this.ToConnect);

th.Start();

}

//连接服务器

private void ToConnect()

{

try

{

IP = IPAddress.Parse(txtIP.Text.Trim());

int point = Convert.ToInt32(txtPoint.Text.Trim());

endpoint = new IPEndPoint(IP, point);

//建立Socket

socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

//建立连接

socket.Connect(endpoint);

//连接成功

lblStatus.Text = “连接成功.”;

while (true)

{

socket.Receive(bs, bs.Length, 0);

pl.Play();

rtxtMsg.AppendText(System.Text.Encoding.Unicode.GetString(bs));

}

}

catch (FormatException)

{ MessageBox.Show(“IP error OR Point error”); }

catch (ArgumentNullException)

{ MessageBox.Show(“IP error OR Point error”); }

catch (Exception)

{

lblStatus.Text = “连接失败,原因: 服务器已停止.”;

}

}

//字体

private void btnFont_Click(object sender, EventArgs e)

{

FontDialog font = new FontDialog();

font.ShowEffects = true;

font.ShowColor = true;

font.MinSize = 12;

font.Font = new Font(“楷体_GB2312”, 18, FontStyle.Bold);

font.Color = Color.Blue;

if (font.ShowDialog() == DialogResult.OK)

{

rtxtSend.Font = font.Font;

rtxtSend.ForeColor = font.Color;

}

}

//关闭连接

private void btnCloseConnect_Click(object sender, EventArgs e)

{

try

{

socket.Close();

lblStatus.Text = “连接已经关闭.”;

}

catch

{

lblStatus.Text = “目前未建立连接.”;

}

}

//发送消息

private void btnSend_Click(object sender, EventArgs e)

{

if (rtxtSend.Text.Trim() == “”)

return;

else if (rtxtSend.Text.Trim().ToLower() == “clear()”)

{

rtxtMsg.Clear();

rtxtSend.Text = “”;

return;

}

else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @”^++$”))

{

string str = rtxtSend.Text.ToLower();

int size = Convert.ToInt32(str.Substring(str.LastIndexOf(‘(‘) + 1,

str.IndexOf(‘)’) – str.LastIndexOf(‘(‘) – 1));

rtxtMsg.Font = new Font(“宋体”, size, FontStyle.Bold);

return;

}

else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @”^++$”))

{

string str = rtxtSend.Text.ToLower();

string size = str.Substring(str.LastIndexOf(‘(‘) + 1, str.IndexOf(‘)’) – str.LastIndexOf(‘(‘) – 1);

if (Convert.ToInt32(size) > rtxtMsg.Text.Length)

return;

}

else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @”^++$”))

{

string str = rtxtSend.Text.ToLower();

string size = str.Substring(str.LastIndexOf(‘(‘) + 1, str.IndexOf(‘)’) – str.LastIndexOf(‘(‘) – 1);

}

else if (rtxtSend.Text.Trim().ToLower() == “exit(0)”)

{

this.Close();

return;

}

try

{

byte bs = new byte;

string user = null;

if (txtUser.Text.Trim() == “在此输入你的名字” || txtUser.Text.Trim() == “”)

{

user = “我”;

bs = Encoding.Unicode.GetBytes(string.Format(“对方说:({0})\r\n{1}\r\n”, DateTime.Now.ToString(),rtxtSend.Text.Trim()));

}

else

{

bs = Encoding.Unicode.GetBytes(string.Format(“{0}说:({1})\r\n{2}\r\n”, txtUser.Text.Trim(),DateTime.Now.ToString(),rtxtSend.Text.Trim()));

user = txtUser.Text.Trim();

}

socket.Send(bs, bs.Length, 0);//发送

txt = string.Format(“{0}说:({1})\r\n{2}\r\n”, user, DateTime.Now.ToString(), rtxtSend.Text.Trim());

int tempLen = rtxtMsg.Text.Length;

rtxtMsg.AppendText(txt);

rtxtMsg.Select(tempLen, txt.Length);

rtxtMsg.SelectionFont = new Font(“宋体”, 10);

rtxtMsg.SelectionColor = Color.Red;

rtxtSend.Clear();

}

catch(Exception ex)

{ MessageBox.Show(“连接尚未建立!无法发送数据!” + ex.Message); }

}

//避开打开多个

private void frmClient_Load(object sender, EventArgs e)

{

foreach (Process p in Process.GetProcesses())

{

if (p.ProcessName == Application.ProductName)//有进程

{

if (p.Id != Process.GetCurrentProcess().Id)//不是当前进程

{

p.Kill();

}

}

}

}

private void frmClient_FormClosing(object sender, FormClosingEventArgs e)

{

try

{

socket.Close();

}

catch(Exception) { }

finally

{

foreach (Process p in Process.GetProcesses())

{

if (p.ProcessName == Application.ProductName)

p.Kill();

}

}

}

private void frmClient_KeyDown(object sender, KeyEventArgs e)

{

if ((e.Control && e.KeyCode == Keys.Enter) || (e.Alt && e.KeyCode == Keys.S))

{

btnSend.PerformClick();

}

}

private void checkBox1_CheckedChanged(object sender, EventArgs e)

{

this.TopMost = checkBox1.Checked;

}

}

c++如何让两个Tcp客户端通过服务器 连接后相互通信?

你这相当于一个软件工裂袜稿程项目,QQ、微信、钉钉都是这种模式,自己好野要开发,即使功能没那么复肆孝杂,也需要开发服务端和客户端两套程序,你可以在网上找找有没有现成的。

tcp 服务器客户端程序的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于tcp 服务器客户端程序,教你如何编写TCP协议的客户端/服务器程序。,C#中TCP进行同步套接字编程,服务器和客户端的工作流程(需要代码和图),c++如何让两个Tcp客户端通过服务器 连接后相互通信?的信息别忘了在本站进行查找喔。


数据运维技术 » 教你如何编写TCP协议的客户端/服务器程序。 (tcp 服务器客户端程序)