-
2021-05-21 10:36:01
https://www.xin3721.com/eschool/python.html
本文实例讲述了C# Socket网络编程技巧。分享给大家供大家参考。具体分析如下:
客户端要连接服务器:首先要知道服务器的IP地址。而服务器里有很多的应用程序,每一个应用程序对应一个端口号
所以客户端想要与服务器中的某个应用程序进行通信就必须要知道那个应用程序的所在服务器的IP地址,及应用程序所对应的端口号
TCP协议:安全稳定,一般不会发生数据丢失,但是效率低。利用TCP发生数据一般经过3次握手(所有效率低,自己百度三次握手)
UDP协议:快速,效率高,但是不稳定,容易发生数据丢失(没有经过三次握手,不管服务器有空没空,信息全往服务器发,所有效率搞,但服务器忙的时候就没办法处理你的数据,容易造成数据丢失,不稳定)
复制代码 代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace Socket通信
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.txtPort.Text = "5000";
this.txtIp.Text = "192.168.137.1";
}
private void btnStart_Click(object sender, EventArgs e)
{
//当点击开始监听的时候,在服务器端创建一个负责监听IP地址跟端口号的Socket
Socket socketWatch = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//Any:提供一个 IP 地址,指示服务器应侦听所有网络接口上的客户端活动。此字段为只读。
IPAddress ip = IPAddress.Any;
//创建端口号对象;将txtPort.Text控件的值设为服务端的端口号
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//监听
socketWatch.Bind(point);
ShowMsg("监听成功");
socketWatch.Listen(10);//连接队列的最大长度 ;即:一个时间点内最大能让几个客户端连接进来,超过长度就进行排队
//等待客户端连接;Accept()这个方法能接收客户端的连接,并为新连接创建一个负责通信的Socket
Thread th = new Thread(Listen); //被线程执行的方法如果有参数的话,参数必须是object类型
Control.CheckForIllegalCrossThreadCalls = false; //因为.net不允许跨线程访问的,所以这里取消跨线程的检查。.net不检查是否有跨线程访问了,所有就不会报: “从不是创建控件“txtLog”的线程访问它” 这个错误了,从而实现了跨线程访问
th.IsBackground = true; //将th这个线程设为后台线程。
//Start(object parameter); parameter:一个对象,包含线程执行的方法要使用的数据,即线程执行Listen方法,Listen的参数
th.Start(socketWatch); //这个括号里的参数其实是Listen()方法的参数。因为Thread th = new Thread(Listen)这个括号里只能写方法名(函数名) 但是Listen()方法是有参数的,所有就要用Start()方法将它的参数添加进来
}
///
/// 等待客户端连接,如果监控到有客户端连接进来就创建一个与之通信的Socket
///
///
void Listen(object o) //这里为什么不直接传递Socket类型的参数呢? 原因是:被线程执行的方法如果有参数的话,参数必须是object类型
{
Socket socketWatch = o as Socket;
while (true) //为什么这里要有个while循环?因为当一个人连接进来的时候创建了与之通信的Socket后就程序就会往下执行了,就不会再回来为第二个人的连接创建负责通信的Socket了。(应该是每个人(每个客户端)创建一个与之通信的Socket)所以要写在循环里。
{
//等待客户端连接;Accept()这个方法能接收客户端的连接,并为新连接创建一个负责通信的Socket
Socket socketSend = socketWatch.Accept();
dic.Add(socketSend.RemoteEndPoint.ToString(), socketSend); //(根据客户端的IP地址和端口号找负责通信的Socket,每个客户端对应一个负责通信的Socket),ip地址及端口号作为键,将负责通信的Socket作为值填充到dic键值对中。
//我们通过负责通信的这个socketSend对象的一个RemoteEndPoint属性,能够拿到远程连过来的客户端的Ip地址跟端口号
ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + "连接成功");//效果:192.168.1.32:连接成功
comboBox1.Items.Add(socketSend.RemoteEndPoint.ToString()); //将连接过来的每个客户端都添加到combBox控件中。
//客户端连接成功后,服务器应该接收客户端发来的消息。
Thread getdata = new Thread(GetData);
getdata.IsBackground = true;
getdata.Start(socketSend);
}
}
Dictionary dic = new Dictionary();
///
/// 不停的接收客户端发送过来的消息
///
///
void GetData(object o)
{
while (true)
{
Socket socketSend = o as Socket;
//将客户端发过来的数据先放到一个字节数组里面去
byte[] buffer = new byte[1024 * 1024 * 2]; //创建一个字节数组,字节数组的长度为2M
//实际接收到的有效字节数; (利用Receive方法接收客户端传过来的数据,然后把数据保存到buffer字节数组中,返回一个接收到的数据的长度)
int r = socketSend.Receive(buffer);
if (r == 0) //如果接收到的有效字节数为0 说明客户端已经关闭了。这时候就跳出循环了。
{
//只有客户端给用户发消息,不可能是发0个长度的字节。即便发空消息,空消息也是有过个长度的。所有接收到的有效字节长度为0就代表客户端已经关闭了
break;
}
//将buffer这个字节数组里面的数据按照UTF8的编码,解码成我们能够读懂的的string类型,因为buffer这个数组的实际存储数据的长度是r个 ,所以从索引为0的字节开始解码,总共解码r个字节长度。
string str = Encoding.UTF8.GetString(buffer, 0, r);
ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + str);
}
}
private void ShowMsg(string str)
{
txtLog.AppendText(str + "\r\n"); //将str这个字符串添加到txtLog这个文本框中。
}
///
/// 服务端给客户端发信息
///
///
///
private void btnSend_Click_1(object sender, EventArgs e)
{
if (comboBox1.SelectedItem == null) //如果comboBox控件没有选中值。就提示用户选择客户端
{
MessageBox.Show("请选择客户端");
return;
}
string str = txtMes.Text; //获取用户输入的内容 (服务端要给客户端发的信息)
byte[] strByte = Encoding.Default.GetBytes(str); //将信息转换成二进制字节数组
string getIp = comboBox1.SelectedItem as string; //comboBox存储的是客户端的(ip+端口号)
Socket socketSend = dic[getIp] as Socket; //根据这个(ip及端口号)去dic键值对中找对应 赋值与客户端通信的Socket【每个客户端都有一个负责与之通信的Socket】
socketSend.Send(strByte); //将信息发送到客户端
}
}
}
开打开始命令 cmd telnet 10.18.16.46 5000 即telnet 服务器ip地址 绑定的端口号
希望本文所述对大家的C#程序设计有所帮助。
更多相关内容 -
socket网络编程大作业
2014-12-21 16:55:03这是有关用户与服务器之间的传输,里面含有tcp协议的,对网络应用有很多的帮助 -
网络编程实验,大作业,学习资料
2021-07-22 15:48:36即时通信客户端心跳机制及文本消息发送功能实现 QT环境,C语言实现,不调库函数 -
2019年天津大学计算机网络Socket编程.rar
2019-06-21 09:39:15本课程源于天津大学开设的计算机网络,使用JAVA实现了一个简易微信,主要功能包括(局域网聊天,添加好友,群发消息,局域网搜索,注册新用户,修改密码等功能),资源包括源...大作业得分100分,有一定的参考价值。 -
C语言Socket编程(计算机网络作业)
2021-05-23 01:41:21最近我计算机网络课程要做作业了,没办法跟着老师一步一步的写C语言的代码,使用的计算就是Socket通信发送消息;代码实现的功能很简单,客户端向服务器端发送消息,服务器端接收客户端发来的消息,并且输出显示到...最近我计算机网络课程要做作业了,没办法跟着老师一步一步的写C语言的代码,使用的计算就是Socket通信发送消息;代码实现的功能很简单,客户端向服务器端发送消息,服务器端接收客户端发来的消息,并且输出显示到屏幕上;代码中的每个socket方法的返回值都应该做判断出错情况,例如:创建SOCKET的创建的时候s句柄(或对象),需要判断返回值是否为INVALID_SOCKET,以及socket的所有操作的返回值是否为SOCKET_ERROR,以保证程序的稳定性,这里只是测试代码。
老师是录制的视频讲解的,其他其中使用的到的方法要求我们自己去查相关的MSDN资料库,如果有不懂的,就自己上网查。
服务器端接收代码:
#include
#pragma comment(lib,"Ws2_32.lib")
#include
#include
void main()
{
WSAData wsd;
WSAStartup(MAKEWORD(2,0),&wsd);
SOCKET s =NULL;
s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
struct sockaddr_in ch;
memset(&ch,0,sizeof(ch));
ch.sin_family=AF_INET;
ch.sin_addr.s_addr=INADDR_ANY;
ch.sin_port=htons(1041);
int b=bind(s,(struct sockaddr *) &ch,sizeof(ch));
#define QUEUE_SIZE 5
int l=listen(s,QUEUE_SIZE);
printf("正在监听本机的1041端口!\n");
SOCKET sc=accept(s,0,0);
printf("客户端已经连接到本机的1041端口!\n");
#define BUF_SIZE 4096
int receByt=0;
while(1)
{
char buf[BUF_SIZE];
receByt=recv(sc,buf,BUF_SIZE,0);
buf[receByt]='\0';
if(receByt>0)
{
printf("接收的消息是:%s\n",buf);
}
else
{
printf("接收消息结束!");
break;
}
}
int ic=closesocket(sc);
int is=closesocket(s);
}
======================================================
客户端发送的代码:
#include
#pragma comment(lib,"Ws2_32.lib")
#include
#include
#include
void main()
{
WSAData wsd;
WSAStartup(MAKEWORD(2,0),&wsd);
SOCKET s =NULL;
s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
struct sockaddr_in ch;
memset(&ch,0,sizeof(ch));
ch.sin_family=AF_INET;
ch.sin_addr.s_addr=inet_addr("127.0.0.1");
ch.sin_port=htons(1041);
int c=connect(s,(struct sockaddr *) &ch,sizeof(ch));
printf("已经连接到服务器的1041端口!现在可以向服务器发送消息了!\n");
#define BUF_SIZE 4096
char info[1024],buf[BUF_SIZE];
while(1)
{
gets(info);
if(info[0]=='\0')
break;
strcpy(buf,info);
int nsend=send(s,buf,strlen(buf),0);
}
int ic=closesocket(s);
}
========================================================================
程序代码经过了优化,并且整合多线程,把接收和发送放到同一个文件中,使用参数模式调用发送和接收模块。增加了创建SOCKET的创建的时候s句柄(或对象)判断返回值是否为INVALID_SOCKET,以及socket的bind操作的返回值是否为SOCKET_ERROR,其他socket的操作应该也判断SOCKET_ERROR,以保证程序的稳定性,这里只是测试代码就不去写这么多了,剩下的就由你个人发挥。
#include
#pragma comment(lib,"Ws2_32.lib")#include#include#include#include
voidReceive();voidSend();voidcreatThread();
SOCKET s=NULL;
pthread_t t[1000];int threadCount=0;void main(int argc,char*argv[])
{
printf("本程序制作人学号:713901040041\n");
printf("程序说明:服务器端和客户端为同一个程序,请使用不同的参数运行.\n");
printf("接收程序请使用 r参数;发送程序请使用 s参数。\n");//printf("len : %d\n", argc);//printf("count %d\n",argc);//printf("value: %s\n",argv[1]);//printf("%d",argv[1][0]=='r');
if(argc<=1)
{
printf("please input program arguments ...\n");
exit(0);
}if(argc>1 && argv[1][0]=='r')
{
printf("run receive ...\n");
Receive();
}if(argc>1 && argv[1][0]=='s')
{
printf("run send ...\n");
Send();
}
}void* receiveWork(void *args)
{
SOCKET sc=accept(s,0,0);if(sc==INVALID_SOCKET)
{
printf("sc Error");
}
creatThread();
printf("----------客户端已经连接到本机的%d线程连接!\n",threadCount-2);#define BUF_SIZE 4096
int receByt=0;while(1)
{charbuf[BUF_SIZE];
receByt=recv(sc,buf,BUF_SIZE,0);
buf[receByt]='\0';if(receByt>0)
{
printf("线程接收的消息是:%s\n",buf);
}else{
printf("客户端已退出,");break;
}
}int ic=closesocket(sc);
printf("服务器结束连接!\n");returnNULL;
}voidcreatThread()
{
pthread_create(&t[threadCount++],NULL,receiveWork,NULL);
}voidReceive()
{
WSAData wsd;
WSAStartup(MAKEWORD(2,0),&wsd);
s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(s==INVALID_SOCKET)
{
printf("socket created Error");
}structsockaddr_in ch;
memset(&ch,0,sizeof(ch));
ch.sin_family=AF_INET;
ch.sin_addr.s_addr=INADDR_ANY;
ch.sin_port=htons(1041);int b=bind(s,(struct sockaddr *) &ch,sizeof(ch));if(b==SOCKET_ERROR)
{
printf("bind 失败,出错代码是:%d\n",WSAGetLastError());
exit(0);
}#define QUEUE_SIZE 5
int l=listen(s,QUEUE_SIZE);
printf("正在监听本机的1041端口!\n");
creatThread();for(int i=0;i<1000;i++)
{
pthread_join(t[i],NULL);
}int is=closesocket(s);
}voidSend()
{
WSAData wsd;
WSAStartup(MAKEWORD(2,0),&wsd);
SOCKET s=NULL;
s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(s==INVALID_SOCKET)
{
printf("socket created Error");
}structsockaddr_in ch;
memset(&ch,0,sizeof(ch));
ch.sin_family=AF_INET;
ch.sin_addr.s_addr=inet_addr("127.0.0.1");
ch.sin_port=htons(1041);int c=connect(s,(struct sockaddr *) &ch,sizeof(ch));
printf("已经连接到服务器的1041端口!现在可以向服务器发送消息了!\n");#define BUF_SIZE 4096
char info[1024],buf[BUF_SIZE];while(1)
{
gets(info);if(info[0]=='\0')break;
strcpy(buf,info);int nsend=send(s,buf,strlen(buf),0);
}int ic=closesocket(s);
}
来源:oschina
链接:https://my.oschina.net/u/4263894/blog/3273951
-
Socket网络编程用JAVA实现聊天工具
2021-06-09 23:36:45计算机网络大作业,简易聊天工具的实现,包含源码和打包后的jar和exe安装文件 -->APP 1.实现点对多点的通信 2.简易的GUI,至少有一树形控件,有文本框 3.能保存聊天数据 注意事项,设置昵称后需要再次连接 -
Python 网络编程之UDP发送接收数据功能示例【基于socket套接字】
2020-09-18 13:57:42主要介绍了Python 网络编程之UDP发送接收数据功能,结合实例形式分析了Python使用socket套接字实现基于UDP协议的数据发送端与接收端相关操作技巧,需要的朋友可以参考下 -
网络程序设计大作业_点餐系统.docx
2021-05-30 17:35:06网络程序设计大作业,C语言socket编程,运用TCP、UDP、广播、多线程等知识点,实现多用户可不同时接入,多用户可同时点餐,单个用户可同时收发等功能。 -
网络编程大作业-聊天室
2021-09-21 15:50:50大二时候完成的网络编程的大作业,用C\C++语言写的一款简易聊天室。目前一个服务器只能连两个客户端,两个以上的我搞不出来。也可以在三台电脑操作,只要输入服务器的IP地址就行了。 使用的编译器:VS2010、VS2019 ...前言:
大二时候完成的网络编程大作业,用C\C++语言写的一款简易聊天室。目前一个服务器只能连两个客户端,两个以上的我搞不出来。也可以在三台电脑操作,只要输入服务器的IP地址就行了。
使用的编译器:VS2010、VS2019演示一下:
左边的是服务器,中间的是客户端1:zhang san,右边是客户端2:li si。
服务器源码:
#include "WinSock2.h" // winsock2.h是套接字接口。 #include "process.h" //process.h 是包含用于和宏指令的作用声明与螺纹和过程一起使用的C标头文件。 #include "stdio.h" //被包含的文件通常是由系统提供的,其扩展名为.h,而stdio为standard input output的缩写,意为“标准输入输出” #include "stdlib.h" //stdlib 头文件里包含了C语言的一些函数,该文件包含了的C语言标准库函数的定义 #include "conio.h" //将conio.h包含入你的程序,使你可以引用其中声明的函数。conio.h不是C标准库中的头文件。 #pragma comment(lib,"ws2_32.lib") // ws2_32.lib是套接字实现。 #define SEND_OVER 1 //已经转发消息 #define SEND_YET 0 //还没转发消息 int Status = SEND_YET; //状态设为未发送 sockaddr_in ClientAddr = { 0 }; //客户端地址 HANDLE g_hRecv1 = NULL; //handle为句柄,用表示对象 void *g_hRecv1=NULL; HANDLE g_hRecv2 = NULL; //客户端信息结构体 struct Client_inf { SOCKET sClient; //客户端套接字 char buf[512]; //数据缓冲区 char userName[20]; //客户端用户名 char IP[20]; //客户端IP UINT_PTR flag; //标记客户端,用来区分不同的客户端,typedef unsigned int_w64 UINT_PTR,是为解决32位与64位编译器的兼容性而设置的关键字 }; typedef Client_inf Client; Client ClientSock[2] = { 0 }; //创建一个客户端结构体 SOCKET ServerSocket=INVALID_SOCKET; unsigned __stdcall ThreadSend(void* param); //声明发送数据的线程函数 unsigned __stdcall ThreadRecv(void* param); //声明接收数据的线程函数 unsigned __stdcall ThreadAccept(void* param); //声明接受请求的线程函数 int main(void) { int ret,len; WSADATA data ; struct sockaddr_in ServerAddr; //服务端地址 unsigned short SERVERPORT = 6666; //服务器监听端口 //初始化套接字 ret = WSAStartup(MAKEWORD(2,2),&data);//WSAStartup函数的返回值是0表示成功 if (SOCKET_ERROR == ret) { printf("WSAstartup error!\n"); return -1; } //创建套接字 ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == ServerSocket) { printf("创建socket失败!\n"); return -2; } //设置服务器地址 ServerAddr.sin_family = AF_INET;//连接方式 ServerAddr.sin_port = htons(SERVERPORT);//服务器监听端口 ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//任何客户端都能连接这个服务器 //绑定服务器 ret = bind(ServerSocket, (struct sockaddr*)&ServerAddr, sizeof(sockaddr));//bind是一组用于函数绑定的模板。 if (SOCKET_ERROR == ret) { printf("bind error!\n"); closesocket(ServerSocket); WSACleanup(); return -3; } //设置监听客户端连接数 ret =listen(ServerSocket,2);//listen是创建一个套接口并监听申请的连接. if (SOCKET_ERROR == ret) { printf("listen error!\n"); closesocket(ServerSocket); WSACleanup(); return -4; } printf("开启聊天成功,等待用户连接....\n"); _beginthreadex(NULL, 0, ThreadAccept, NULL, 0, 0); //启动接受连接线程 int k=0; while(k<100) //让主线程休眠,不让它关闭TCP连接. { Sleep(10000000); k++; } //关闭套接字 for (int j = 0;j < 2;j++) { if (ClientSock[j].sClient != INVALID_SOCKET) closesocket(ClientSock[j].sClient); } closesocket(ServerSocket); WSACleanup(); return 0; } //发送数据线程函数的定义 unsigned __stdcall ThreadSend(void* param) //param形参 { int ret = 0; int flag = *(int*)param; //int*是把param从void*强制转化为int*,要不然取值的时候系统会不知所措,外面的*就是取值操作,取param这个地址里面保存的整型值 SOCKET client = INVALID_SOCKET; //创建一个临时套接字来存放要转发的客户端套接字 char temp[512] = { 0 }; //创建一个临时的数据缓冲区,用来存放接收到的数据 memcpy(temp, ClientSock[!flag].buf, sizeof(temp)); //拷贝 sprintf( ClientSock[flag].buf, "%s: %s", ClientSock[!flag].userName, temp);//添加一个用户名头 if (strlen(temp) != 0 && Status == SEND_YET&&temp!="\n"&&(*temp!=' ')) //如果数据不为空且还没转发则转发 { ret = send( ClientSock[flag].sClient, ClientSock[flag].buf, sizeof( ClientSock[flag].buf), 0); }//send()是一个计算机函数,功能是向一个已经连接的socket发送数据,如果无错误,返回值为所发送数据的总数,否则返回SOCKET_ERROR。 if (SOCKET_ERROR == ret) { return 1; } Status = SEND_OVER; //转发成功后设置状态为已转发 return 0; } //接受数据线程函数的定义 unsigned __stdcall ThreadRecv(void* param) { SOCKET client = INVALID_SOCKET; //客户端套接字 int flag = 0; if (*(int*)param == ClientSock[0].flag) //判断是哪个客户端发来的消息 { client = ClientSock[0].sClient; flag = 0; } else if (*(int*)param == ClientSock[1].flag) { client = ClientSock[1].sClient; flag = 1; } char temp[512] = { 0 }; //临时数据缓冲区 while (1) { memset(temp, 0, sizeof(temp)); int ret = recv(client, temp, sizeof(temp), 0); //接收数据 if (SOCKET_ERROR == ret) continue; Status = SEND_YET; //设置转发状态为未转发 if(client==ClientSock[0].sClient ) { //设置防止出现自己给自己发消息的BUG flag=1; } else { flag=0; } memcpy( ClientSock[!flag].buf, temp, sizeof( ClientSock[!flag].buf)); _beginthreadex(NULL, 0, ThreadSend, &flag, 0, NULL); //开启一个转发线程,flag标记着要转发给哪个客户端 } return 0; } //接受请求线程函数的定义 unsigned __stdcall ThreadAccept(void* param) { int i = 0; int temp1 = 0, temp2 = 0; { while (i < 2) //表明只允许两个客户端连接 { if (ClientSock[i].flag != 0) { ++i; continue; } //如果有客户端申请连接就接受连接 int len= sizeof(ClientAddr); int ret = ClientSock[i].sClient = accept(ServerSocket, (SOCKADDR*)&ClientAddr, &len);//accept()是在一个套接口接受的一个连接。 if (INVALID_SOCKET == ret) { printf("accept error!\n"); closesocket(ServerSocket); WSACleanup(); return -1; } recv(ClientSock[i].sClient, ClientSock[i].userName, sizeof(ClientSock[i].userName), 0); //接收用户名 printf(" 成功连上聊天用户!IP:%s ,Port: %d,UerName: %s\n",inet_ntoa(ClientAddr.sin_addr), htons(ClientAddr.sin_port), ClientSock[i].userName); memcpy(ClientSock[i].IP, inet_ntoa(ClientAddr.sin_addr), sizeof(ClientSock[i].IP)); //记录客户端IP ClientSock[i].flag = ClientSock[i].sClient; //不同的socke有不同UINT_PTR类型的数字来标识 i++; } i = 0; if (ClientSock[0].flag != 0 && ClientSock[1].flag != 0 ) //当两个用户都连接上服务器后才进行消息转发 { if (ClientSock[0].flag != temp1) //每次断开一个连接后再次连上会新开一个线程,导致cpu使用率上升,所以要关掉旧的,,int temp1 = 0, temp2 = 0; { if (g_hRecv1) //这里关闭了线程句柄 CloseHandle(g_hRecv1); g_hRecv1 = (HANDLE)_beginthreadex(NULL, 0, ThreadRecv, &ClientSock[0].flag, 0, NULL); //开启2个接收消息的线程 } if (ClientSock[1].flag != temp2) { if (g_hRecv2) CloseHandle(g_hRecv2); g_hRecv2 = (HANDLE)_beginthreadex(NULL, 0, ThreadRecv, &ClientSock[1].flag, 0, NULL); } } temp1 = ClientSock[0].flag; //防止ThreadRecv线程多次开启 temp2 = ClientSock[1].flag; Sleep(2000); } return 0; }
客户端源码:
#include "WinSock2.h" // winsock2.h是套接字接口。 #include "process.h" //process.h 是包含用于和宏指令的作用声明与螺纹和过程一起使用的C标头文件。 #include "stdio.h" //被包含的文件通常是由系统提供的,其扩展名为.h,而stdio为standard input output的缩写,意为“标准输入输出” #include "stdlib.h" //stdlib 头文件里包含了C语言的一些函数,该文件包含了的C语言标准库函数的定义 #include "conio.h" //将conio.h包含入你的程序,使你可以引用其中声明的函数。conio.h不是C标准库中的头文件。 #pragma comment(lib,"ws2_32.lib") // ws2_32.lib是套接字实现。 #define RECV_OVER 1 #define RECV_YET 0 char userName[20] = { 0 }; int Status = RECV_YET; unsigned __stdcall ThreadRecv(void* param); //接受数据的线程 unsigned __stdcall ThreadSend(void* param); //发送数据的线程 int main(void) { WSADATA wsaData = { 0 }; SOCKET ClientSocket = INVALID_SOCKET; //客户端套接字 sockaddr_in ServerAddr = { 0 }; //服务端地址,SOCKADDR_IN为结构体,可以小写 unsigned short SERVERPORT = 6666; //初始化套接字 WSADATA data; int ret=WSAStartup(MAKEWORD(2,2),&data); //WSAStartup函数的返回值是0表示成功 if (SOCKET_ERROR==ret) { printf("WSAStartup 启动错误!\n"); return -1; } //创建套接字 ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if ( INVALID_SOCKET == ClientSocket) { printf("socket创建失败!\n"); WSACleanup(); return -1; } //输入服务器IP printf("请输入服务器的IP:"); char IP[32] = { 0 }; gets_s(IP,31); //设置服务器地址 ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(SERVERPORT); //服务器端口 ServerAddr.sin_addr.S_un.S_addr = inet_addr(IP); //服务器地址 printf("正在努力连接服务器.....\n"); //连接服务器 ret=connect(ClientSocket,(sockaddr*)&ServerAddr,sizeof(ServerAddr)); if ( SOCKET_ERROR ==ret) { printf("connect连接服务器失败!\n"); closesocket(ClientSocket); WSACleanup(); return -1; } printf("成功连上服务器 IP:%s Port:%d\n",IP,htons(ServerAddr.sin_port)); printf("欢迎登录66微聊聊天室!\n"); printf("请输入你的名字: "); gets_s(userName,20); send(ClientSocket, userName, sizeof(userName), 0); printf("\n\n"); _beginthreadex(NULL, 0, ThreadRecv, &ClientSocket, 0, NULL); //启动接收和发送消息线程 _beginthreadex(NULL, 0, ThreadSend, &ClientSocket, 0, NULL); for (int k = 0;k < 1000;k++) // 让主线程休眠,不让它关闭TCP连接 { Sleep(10000000); } closesocket(ClientSocket); WSACleanup(); return 0; } unsigned __stdcall ThreadRecv(void* param) { char buf[512] = { 0 }; while (1) { int ret = recv(*(SOCKET*)param, buf, sizeof(buf), 0); //先强行转化为SOCKET*,不然void*直接引用会出错 if (SOCKET_ERROR == ret) { Sleep(500); //将进程挂起一段时间,即停下来0.5s再继续 continue; } if (strlen(buf) != 0) //判断缓冲区是不是有数据,有就打印出来! { printf("%s\n", buf); Status = RECV_OVER; //把状态设为已接收 } else Sleep(100); } return 0; } unsigned __stdcall ThreadSend(void* param) { char buf[512] = { 0 }; int ret = 0; while (1) { int c = getch(); //在头文件conio.h有定义,此函数是一个不回显函数,当用户按下某个字符时,此函数自动读取,无需按回车 if(c == 72 || c == 0 || c == 68) //遇到这几个值getch就会自动跳过 continue; printf("%s: ", userName); gets_s(buf,511); //此函数在stdio.h中定义,第二参数就是允许输入长度,留一位补零,否则溢出 ret = send(*(SOCKET*)param, buf, sizeof(buf), 0); if (ret == SOCKET_ERROR) if (ret == SOCKET_ERROR) { return 1; } if(strcmp(buf,"bye") == 0||strcmp(buf,"再见")==0) { printf("您已退出聊天室!\n"); break; } } return 0; }
最后:
需要代码的可以自行下载。下载链接
下载操作:
-
C++网络编程实例(socket)
2021-11-01 11:06:07C++网络编程实例(socket) 功能 实现基于sokcet的Cpp服务端 TIPS:功能包括接收客户端的数据,向客户端发送数据。 源码 #define _WINSOCK_DEPRECATED_NO_WARNINGS #include <iostream> //#include <...C++网络编程实例(socket)
功能
实现基于sokcet的Cpp服务端
TIPS:功能包括接收客户端的数据,向客户端发送数据。
源码
#define _WINSOCK_DEPRECATED_NO_WARNINGS #include <iostream> //#include <windows.h> #include <WinSock2.h> #pragma comment(lib,"ws2_32") using std::cout; using std::endl; using std::cin; int main() { system("chcp 65001"); //SetConsoleOutputCP(65001); WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData);//启动window动态网络库 //1.创建socket //SOCKET == 句柄 == 文件描述符 == 套接字 //socket(协议族类型,协议类型,0); //协议族类型 IPV4(AF_INET) IPV6 //协议类型 TCP(SOCK_STREAM),UDP(SOCK_DROP) SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);//IPPROTO_TCP if (serverSocket == INVALID_SOCKET) { cout << "创建socket失败" << endl; return 0; } //2.绑定ip和端口号 //127.0.0.1 永远指向本机 //0.0.0.o 绑定所有网卡的ip SOCKADDR_IN serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(7890);//host to networks short,将主机字节序转化为网络字节序 serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");//点分十进制转换为10进制 if (SOCKET_ERROR == bind(serverSocket, (sockaddr *)&serverAddr, sizeof(SOCKADDR_IN))) { cout << "bind 失败" << endl; return 0; } cout << "bind 成功" << endl; //3.监听,提示本机的操作系统 if (INVALID_SOCKET == listen(serverSocket, 5)) { cout << "listen 失败" << endl; return 0; } cout << "listen 成功" << endl; while(true) { //4.等待客户端连接 SOCKADDR_IN clientAddr; int addrLen = sizeof(SOCKADDR_IN); SOCKET clientSocket = accept(serverSocket, (SOCKADDR *)&clientAddr, &addrLen); if (INVALID_SOCKET == clientSocket) { cout << "客户端连接失败 " << endl; return 0; } cout << "client ok " << inet_ntoa(clientAddr.sin_addr) << endl; cout << "port " << ntohs(clientAddr.sin_port) << endl; //5.收发数据 //接收数据 char recvBuffer[1024]{ 0 }; int nRecv = recv(clientSocket, recvBuffer, 1024, 0); cout << "recvLen:" << nRecv << "内容:" << recvBuffer << endl; //发送数据 int nSend = send(clientSocket, recvBuffer, nRecv, 0); cout << "send Len:" << nSend << endl; //6.关闭客户端 closesocket(clientSocket); } //7.关闭服务端 closesocket(serverSocket); WSACleanup();//卸载window动态网络库 return 0; }
效果
TIPS:利用sokit模拟工具模拟一个客户端终端。
-
SOCKET 网络编程 计算机网络 作业 客户端 服务器端 client svever
2009-05-31 10:56:17SOCKET 网络编程 计算机网络 作业 客户端 服务器端 client svever SOCKET 网络编程 计算机网络 作业 客户端 服务器端 client svever -
【Linux】socket网络编程基础知识
2021-07-28 06:38:03此次大作业涉及到Linux课程第十章:网络编程的相关知识,因此着重以老师PPT上的内容为要,进行代码编写。以C/C++为主。 实验内容和要求 实现以下程序 1.服务器端存放共享变量var_temp,该值从终端(键盘)中输入。 2.... -
通信网络编程作业整理
2017-12-05 11:07:47socket 是“套接字”的意思,是计算机之间进行通信的一种约定,也可以认为是一种技术。学习 socket,就是学习计算机之间如何通信,并能够...值得欣慰的是,两大平台下的 socket 编程非常相似,并不会增加多少学习成本。 -
计算机网络(Socket编程)
2020-07-29 10:58:514. Socket编程 4.1 socket的基本步骤 创建 Socket 连接时,可以指定使用的传输层协议,Socket 可以支持不同的传输层协 议(TCP 或 UDP),当使用 TCP 协议进行连接时,该 Socket 连接就是一个 TCP 连接。 Server 端... -
socket编程与大文件传输
2021-08-13 07:07:39前段时间通过学习socket编程实现了客户端与服务器之间的大尺寸文件的传输,最近在参加一些笔试时,也遇到了socket的问题,遂整理出一些东西出来,和大家分享,也便于对这方面不了解的朋友迅速建立概念。首先介绍一下... -
python网络编程-socket编程
2018-06-02 09:20:08互联网协议:Socket是介于应用层和传输层之间Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来... -
基于Socket的网络通信大作业 含可运行C代码
2016-07-01 08:02:022016年做的TCP/IP大作业,包含摘要、代码、参考书籍等所有必要元素 -
【Linux】socket网络编程之服务器与客户端的数据交互
2021-07-29 08:41:11【Linux】网络编程之服务器与客户端的数据交互前言参考argc !...本博文基于作者上一篇博文(Linux网络编程基础知识),主要用于完善作业,代码改动其实很小。 argc !=2是什么意思 What does argc mea -
Java实现socket网络编程
2021-04-29 11:22:57本文根据韩顺平老师的TCP网络编程进行总结 感谢B站老韩 仅总结了TCP编程的部分 UDP只是看了一下 没有进行记录笔记 本篇文章仅供自己学习使用,如有任何错误,请与我联系指正修改,十分感谢! Java实现TCP编程的一些... -
华农网络编程socket通信
2014-03-22 21:40:53华南农业大学 网络编程 socket 通信 server client 刘汉星老师作业 -
Qt网络编程项目:斗地主+详细设计文档
2020-09-15 19:52:49大一小学期布置的大作业,要求利用qt的网络编程制作的斗地主项目。附有详细设计文档,新手可参考,大神请无视。 -
网络编程学习(1)—— 基于SOCKET实现简单套接字通信
2022-03-01 21:55:55网络编程学习(1)—— 基于SOCKET实现简单套接字通信套接字通信简单理解网络通信简单理解简单套接字通信类比代码实现运行结果优化:通信循环 套接字通信简单理解 网络通信简单理解 要想实现网络通信,简单理解就是... -
网络编程作业(winsocket实现聊天程序)
2014-05-27 10:29:20研究生网络编程作业,所有的结构与代码均由自己实现,适合用于上交老师布置的聊天程序编写作业 -
Java使用Socket网络编程
2019-12-07 10:17:59网络编程 回顾: 1 多线程访问临界资源---线程安全问题 2 线程同步: 同步代码块 synchronized (锁){ //锁多个线程使用同一个锁 this 代码 } 同步方法 public synchronized void sale(){ //this } ... -
VC++网络编程 MFC Socket编程
2021-04-15 12:48:34一、建立项目 启动VS2010——选择MFC——MFC应用程序——项目名称ChatClient——确定 ...创建类名为CClientSocket的客户Socket对象,下面给工程添加类,选择菜单命令 项目——添加类 如下图所示 在 -
Linux下TCP Socket编程实例
2022-02-16 15:07:28Linux下TCP Socket编程实例Socket是应用层与TCP/IP协议族通信的中间软件抽象层1. socket套接字2. 套接字描述符3. 文件描述符和文件指针的区别4. 基本的SOCKET接口函数4.1、socket()函数4.2、bind()函数4.3、listen()... -
基于UDP协议网络Socket编程(java实现C/S通信案例)
2020-10-11 21:33:41本篇详细记录运用java进行网络编程,基于UDP套接字(Socket)实现服务器与客户端间的通信,在实战案例中更深刻理解UDP的实现原理,掌握UDP实践应用步骤。 -
socket网络编程解决TCP客户端和服务端问题——python
2022-03-31 00:32:55socket网络编程解决TCP客户端和服务端问题——python问题描述实验准备与环境实验步骤结论 问题描述 A和B采用TCP通信,连接成功以后,A的起始序列号是500,B的起始序列号是800,A首先发起通信,发出消息:Hello!(6... -
基于TCP协议的套接字网络(socket)编程
2021-01-19 20:04:47基于TCP协议的套接字网络(socket)编程 一、什么是socket 1、介绍: 在了解了osI七层协议之后,我们看到,应用层与传输层之间,有着一个socket的抽象层,这里的抽象层并不存在于osI七层协议之中,这里的socket抽象层...