socket编程。怎么实现数据包的转发?C语言版的。
网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。
下面用Socket实现一个windows下的c语言socket通信例子,这里我们客户端传递一个字符串,服务器端进行接收。
【服务器端】#include "stdafx.h"#include #include #include #define SERVER_PORT 5208 //侦听端口void main(){ WORD wVersionRequested; WSADATA wsaData; int ret, nLeft, length; SOCKET sListen, sServer; //侦听套接字,连接套接字 struct sockaddr_in saServer, saClient; //地址信息 char *ptr;//用于遍历信息的指针 //WinSock初始化 wVersionRequested=MAKEWORD(2, 2); //希望使用的WinSock DLL 的版本 ret=WSAStartup(wVersionRequested, &wsaData); if(ret!=0) { printf("WSAStartup() failed!
"); return; } //创建Socket,使用TCP协议 sListen=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sListen == INVALID_SOCKET) { WSACleanup(); printf("socket() faild!
"); return; } //构建本地地址信息 saServer.sin_family = AF_INET; //地址家族 saServer.sin_port = htons(SERVER_PORT); //注意转化为网络字节序 saServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //使用INADDR_ANY 指示任意地址 //绑定 ret = bind(sListen, (struct sockaddr *)&saServer, sizeof(saServer)); if (ret == SOCKET_ERROR) { printf("bind() faild! code:%d
", WSAGetLastError()); closesocket(sListen); //关闭套接字 WSACleanup(); return; } //侦听连接请求 ret = listen(sListen, 5); if (ret == SOCKET_ERROR) { printf("listen() faild! code:%d
", WSAGetLastError()); closesocket(sListen); //关闭套接字 return; } printf("Waiting for client connecting!
"); printf("Tips: Ctrl+c to quit!
"); //阻塞等待接受客户端连接 while(1)//循环监听客户端,永远不停止,所以,在本项目中,我们没有心跳包。 { length = sizeof(saClient); sServer = accept(sListen, (struct sockaddr *)&saClient, &length); if (sServer == INVALID_SOCKET) { printf("accept() faild! code:%d
", WSAGetLastError()); closesocket(sListen); //关闭套接字 WSACleanup(); return; } char receiveMessage[5000]; nLeft = sizeof(receiveMessage); ptr = (char *)&receiveMessage; while(nLeft>0) { //接收数据 ret = recv(sServer, ptr, 5000, 0); if (ret == SOCKET_ERROR) { printf("recv() failed!
"); return; } if (ret == 0) //客户端已经关闭连接 { printf("Client has closed the connection
"); break; } nLeft -= ret; ptr += ret; } printf("receive message:%s
", receiveMessage);//打印我们接收到的消息。 } // closesocket(sListen); // closesocket(sServer); // WSACleanup();}【客户端】#include "stdafx.h"#include #include #include #define SERVER_PORT 5208 //侦听端口void main(){ WORD wVersionRequested; WSADATA wsaData; int ret; SOCKET sClient; //连接套接字 struct sockaddr_in saServer; //地址信息 char *ptr; BOOL fSuccess = TRUE; //WinSock初始化 wVersionRequested = MAKEWORD(2, 2); //希望使用的WinSock DLL的版本 ret = WSAStartup(wVersionRequested, &wsaData); if(ret!=0) { printf("WSAStartup() failed!
"); return; } //确认WinSock DLL支持版本2.2 if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2) { WSACleanup(); printf("Invalid WinSock version!
"); return; } //创建Socket,使用TCP协议 sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sClient == INVALID_SOCKET) { WSACleanup(); printf("socket() failed!
"); return; } //构建服务器地址信息 saServer.sin_family = AF_INET; //地址家族 saServer.sin_port = htons(SERVER_PORT); //注意转化为网络节序 saServer.sin_addr.S_un.S_addr = inet_addr("192.168.1.127"); //连接服务器 ret = connect(sClient, (struct sockaddr *)&saServer, sizeof(saServer)); if (ret == SOCKET_ERROR) { printf("connect() failed!
"); closesocket(sClient); //关闭套接字 WSACleanup(); return; } char sendMessage[]="hello this is client message!"; ret = send (sClient, (char *)&sendMessage, sizeof(sendMessage), 0); if (ret == SOCKET_ERROR) { printf("send() failed!
"); } else printf("client info has been sent!"); closesocket(sClient); //关闭套接字 WSACleanup();}
先要理解socket是什么?
简单的说socket是一个全双工的通信通道,
即使用TCP或者UDP通信时均可以在发送消息的同时接受消息,
它不区分是否是服务器。
根据这个概念你的问题就很好回答。
》当客户端与服务器连接后。有什么方法使服务器可以随时随地发消息给客户端?
》我现在只能。客户端发个消息给服务器。服务器才能发个消息给客户端。也就是说客户端不发消息。服务器就没法发消息给客户端。
》求大牛给个思路。当连接后。客户端与服务器双方可以随时随地通信!
使用多线程,一个维持接受逻辑,一个维持送信逻辑,即可完成同时接受及发送。
客户端及服务器端均做上述设置。
而你的做法是在一个线程中执行接受与送信,因此只能按照顺序逻辑完成接收与送信。
关键点是多线程。
网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。
下面用Socket实现一个windows下的c语言socket通信例子,用客户端传递一个字符串,服务器端进行接收。
【服务器端】
#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#include <winsock2.h>
#define SERVER_PORT 5208 //侦听端口
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int ret, nLeft, length;
SOCKET sListen, sServer; //侦听套接字,连接套接字
struct sockaddr_in saServer, saClient; //地址信息
char *ptr;//用于遍历信息的指针
//WinSock初始化
wVersionRequested=MAKEWORD(2, 2); //希望使用的WinSock DLL 的版本
ret=WSAStartup(wVersionRequested, &wsaData);
if(ret!=0)
{
printf("WSAStartup() failed!\n");
return;
}
//创建Socket,使用TCP协议
sListen=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sListen == INVALID_SOCKET)
{
WSACleanup();
printf("socket() faild!\n");
return;
}
//构建本地地址信息
saServer.sin_family = AF_INET; //地址家族
saServer.sin_port = htons(SERVER_PORT); //注意转化为网络字节序
saServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //使用INADDR_ANY 指示任意地址
//绑定
ret = bind(sListen, (struct sockaddr *)&saServer, sizeof(saServer));
if (ret == SOCKET_ERROR)
{
printf("bind() faild! code:%d\n", WSAGetLastError());
closesocket(sListen); //关闭套接字
WSACleanup();
return;
}
//侦听连接请求
ret = listen(sListen, 5);
if (ret == SOCKET_ERROR)
{
printf("listen() faild! code:%d\n", WSAGetLastError());
closesocket(sListen); //关闭套接字
return;
}
printf("Waiting for client connecting!\n");
printf("Tips: Ctrl+c to quit!\n");
//阻塞等待接受客户端连接
while(1)//循环监听客户端,永远不停止
{
length = sizeof(saClient);
sServer = accept(sListen, (struct sockaddr *)&saClient, &length);
if (sServer == INVALID_SOCKET)
{
printf("accept() faild! code:%d\n", WSAGetLastError());
closesocket(sListen); //关闭套接字
WSACleanup();
return;
}
char receiveMessage[5000];
nLeft = sizeof(receiveMessage);
ptr = (char *)&receiveMessage;
while(nLeft>0)
{
//接收数据
ret = recv(sServer, ptr, 5000, 0);
if (ret == SOCKET_ERROR)
{
printf("recv() failed!\n");
return;
}
if (ret == 0) //客户端已经关闭连接
{
printf("Client has closed the connection\n");
break;
}
nLeft -= ret;
ptr += ret;
}
printf("receive message:%s\n", receiveMessage);//打印我们接收到的消息。
}
// closesocket(sListen);
// closesocket(sServer);
// WSACleanup();
}
【客户端】
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#define SERVER_PORT 5208 //侦听端口
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int ret;
SOCKET sClient; //连接套接字
struct sockaddr_in saServer; //地址信息
char *ptr;
BOOL fSuccess = TRUE;
//WinSock初始化
wVersionRequested = MAKEWORD(2, 2); //希望使用的WinSock DLL的版本
ret = WSAStartup(wVersionRequested, &wsaData);
if(ret!=0)
{
printf("WSAStartup() failed!\n");
return;
}
//确认WinSock DLL支持版本2.2
if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup();
printf("Invalid WinSock version!\n");
return;
}
//创建Socket,使用TCP协议
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sClient == INVALID_SOCKET)
{
WSACleanup();
printf("socket() failed!\n");
return;
}
//构建服务器地址信息
saServer.sin_family = AF_INET; //地址家族
saServer.sin_port = htons(SERVER_PORT); //注意转化为网络节序
saServer.sin_addr.S_un.S_addr = inet_addr("192.168.1.127");
//连接服务器
ret = connect(sClient, (struct sockaddr *)&saServer, sizeof(saServer));
if (ret == SOCKET_ERROR)
{
printf("connect() failed!\n");
closesocket(sClient); //关闭套接字
WSACleanup();
return;
}
char sendMessage[]="hello this is client message!";
ret = send (sClient, (char *)&sendMessage, sizeof(sendMessage), 0);
if (ret == SOCKET_ERROR)
{
printf("send() failed!\n");
}
else
printf("client info has been sent!");
closesocket(sClient); //关闭套接字
WSACleanup();
}
CPU插槽有哪些区别 CPU插槽类型介绍【详解】-搜狗输入法
二、ocket754 ocket754是2003年9月AMD64位桌面平台最初发布时的标准插槽,是目前低端的Athlon64和高端的Sempron所对应的插槽标准。具有754个CPU针脚插孔,支持200MHz外频和800MHz的HyperTransport总线频率,但不支持双通道内存技术。三、Socket939 Socket939是AMD公司2004年6月才发布的64位桌面平台标准,是...
CPU插槽有哪些区别 CPU插槽类型介绍【详解】-搜狗输入法
二、ocket754 ocket754是2003年9月AMD64位桌面平台最初发布时的标准插槽,是目前低端的Athlon64和高端的Sempron所对应的插槽标准。具有754个CPU针脚插孔,支持200MHz外频和800MHz的HyperTransport总线频率,但不支持双通道内存技术。三、Socket939 Socket939是AMD公司2004年6月才发布的64位桌面平台标准,是...
CPU插槽有哪些区别 CPU插槽类型介绍【详解】
二、ocket754 ocket754是2003年9月AMD64位桌面平台最初发布时的标准插槽,是目前低端的Athlon64和高端的Sempron所对应的插槽标准。具有754个CPU针脚插孔,支持200MHz外频和800MHz的HyperTransport总线频率,但不支持双通道内存技术。三、Socket939 Socket939是AMD公司2004年6月才发布的64位桌面平台标准,是...
仍苗双歧: Client 端直接创建socket的时候指定服务器IP 和端口号 public class Client { private Socket socket; private BufferedReader input ; public void getConnect() throws Exception{ //获得服务器链接,第一个参数是IP地址,第二个参数是端口号 socket = ...
文水县17035834817: 如何用java写数据包? - ?
仍苗双歧: 你好,java中的socket编程,要把数据最后转成byte[]来进行通信,对于你这种情况,我认为你至少有两种方法可行1、在java中也整一个类对象,等效于你这里的struct,然后使用java中把Object转换成byte[]的方法2、把struct里的数据按照一定的...
文水县17035834817: java怎么通过socket发送16进制数据包 - ?
仍苗双歧: getOutputStream(),从连接获取输入流对象. 这个对象可以和BufferedOutputStream,OutputStreamWriter等配合使用; 建立BufferedOutputStream对象 BufferedOutputStream br=new BufferedOutputStream(socket.getOutputStream()); 调用BufferedOutputStream对象的,write向流中写入数据.
文水县17035834817: 怎么实现UDP数据包的拆包组包发送与接收 - ?
仍苗双歧: 如果你个人计算机用户,接受的数据包应该比发送的数据包大几十倍才正常(根据用户使用计算机时间长短决定).因为大家平时浏览网页、下载软件等都不需要发送多少数据,而主要是接受.如果普通计算机用户发送数据包多于收到的那就要提起警惕了.
文水县17035834817: 请教高手:针对某台计算机的某一个端口发送数据包!请问如何实现? - ?
仍苗双歧: 1 使用Socket编程,可以发送任意数据2 使用Telnet程序,可以发送文本数据
文水县17035834817: 请问下C++ linux socket 数据包怎么定义及应用? - ?
仍苗双歧: socket数据包怎么定义以及应用?你是准备自己组织socket的数据,自己实现和处理协议?那你准备从哪一层开始?IP层?更低层?具体的数据组织的话,你需要搜下ip数据包的是如何封装的,还有tcp和udp的数据包的组织.为什么不用bsd的...
文水县17035834817: python中使用socket编程,如何能够通过UDP传递一个列表类型的数据? - ?
仍苗双歧: Python中的 list 或者 dict 都可以转成JSON字符串来发送,接收后再转回来.首先 import json然后,把 list 或 dict 转成 JSON json_string = json.dumps(list_or_dict)用socket发送过去,例如 s.sendto(json_string, address) 对方用socket接收,例如 ...
文水县17035834817: C语言 socket封包和解包 - ?
仍苗双歧: 所谓的封包,就是把各个类型的数据转换成字节数组, 反之拆包就是把对应的字节数组转换为字符串,integer,short,double类型.具体的定义要参考协议包的定义.常用方法有: Encoding.GetString(byte[]), Encoding.GetBytes(string); BitConverter.GetBytes(); BitConverter.ToInt32(byte[], int); 等等.
文水县17035834817: 如何用C语言实现向某个IP发送数据包(例如4个浮点数)??
仍苗双歧: 楼上说的不错,window下使用封装好的socket api可以做到这点 具体,要看选择什么样的通信类型,tcp还是udp ,然后根据api的使用,一般来说步骤是: 创建socket 绑定socket 侦听(tcp or udp决定) 接受msg 返回msg 这样就可以实现通信了
文水县17035834817: 如何用java写数据包??
仍苗双歧: 你的问题是关于socket通信,字节流传递,在问问上没有办法说清楚,因为太复杂了. 还有你的数据包的定义看着有点类似C语言的写法,在java里不是这样定义数据包的. 给你指一个方向吧,如果你想快速的实现网络通信你可以去了解一下MINA框架,去网上搜一下吧. MINA一个很好的通信框架,基于java的nio技术实现,基本上不用你去理解通信层的实现,按照他的架构去实现就可以完成通信. 不过有时间还是需要好好学习一下底层的socket通信.