socket编程。怎么实现数据包的转发?C语言版的。

作者&投稿:励肯 (若有异议请与网页底部的电邮联系)
C语言socket编程怎么实现2个客户端之间通信~

网络的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,这是程序员都知道的。而且,面试的时候,我们也会问对方会不会Socket编程?一般来说,很多人都会说,Socket编程基本就是listen,accept以及send,write等几个基本的操作。是的,就跟常见的文件操作一样,只要写过就一定知道。对于网络编程,我们也言必称TCP/IP,似乎其它网络协议已经不存在了。对于TCP/IP,我们还知道TCP和UDP,前者可以保证数据的正确和可靠性,后者则允许数据丢失。最后,我们还知道,在建立连接前,必须知道对方的IP地址和端口号。除此,普通的程序员就不会知道太多了,很多时候这些知识已经够用了。最多,写服务程序的时候,会使用多线程来处理并发访问。我们还知道如下几个事实:1。一个指定的端口号不能被多个程序共用。比如,如果IIS占用了80端口,那么Apache就不能也用80端口了。2。很多防火墙只允许特定目标端口的数据包通过。3。服务程序在listen某个端口并accept某个连接请求后,会生成一个新的socket来对该请求进行处理。于是,一个困惑了我很久的问题就产生了。如果一个socket创建后并与80端口绑定后,是否就意味着该socket占用了80端口呢?如果是这样的,那么当其accept一个请求后,生成的新的socket到底使用的是什么端口呢(我一直以为系统会默认给其分配一个空闲的端口号)?如果是一个空闲的端口,那一定不是80端口了,于是以后的TCP数据包的目标端口就不是80了--防火墙一定会组织其通过的!实际上,我们可以看到,防火墙并没有阻止这样的连接,而且这是最常见的连接请求和处理方式。我的不解就是,为什么防火墙没有阻止这样的连接?它是如何判定那条连接是因为connet80端口而生成的?是不是TCP数据包里有什么特别的标志?或者防火墙记住了什么东西?后来,我又仔细研读了TCP/IP的协议栈的原理,对很多概念有了更深刻的认识。比如,在TCP和UDP同属于传输层,共同架设在IP层(网络层)之上。而IP层主要负责的是在节点之间(End to End)的数据包传送,这里的节点是一台网络设备,比如计算机。因为IP层只负责把数据送到节点,而不能区分上面的不同应用,所以TCP和UDP协议在其基础上加入了端口的信息,端口于是标识的是一个节点上的一个应用。除了增加端口信息,UPD协议基本就没有对IP层的数据进行任何的处理了。而TCP协议还加入了更加复杂的传输控制,比如滑动的数据发送窗口(Slice Window),以及接收确认和重发机制,以达到数据的可靠传送。不管应用层看到的是怎样一个稳定的TCP数据流,下面传送的都是一个个的IP数据包,需要由TCP协议来进行数据重组。所以,我有理由怀疑,防火墙并没有足够的信息判断TCP数据包的更多信息,除了IP地址和端口号。而且,我们也看到,所谓的端口,是为了区分不同的应用的,以在不同的IP包来到的时候能够正确转发。TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口。就像操作系统会提供标准的编程接口,比如Win32编程接口一样,TCP/IP也必须对外提供编程接口,这就是Socket编程接口--原来是这么回事啊!在Socket编程接口里,设计者提出了一个很重要的概念,那就是socket。这个socket跟文件句柄很相似,实际上在BSD系统里就是跟文件句柄一样存放在一样的进程句柄表里。这个socket其实是一个序号,表示其在句柄表中的位置。这一点,我们已经见过很多了,比如文件句柄,窗口句柄等等。这些句柄,其实是代表了系统中的某些特定的对象,用于在各种函数中作为参数传入,以对特定的对象进行操作--这其实是C语言的问题,在C++语言里,这个句柄其实就是this指针,实际就是对象指针啦。现在我们知道,socket跟TCP/IP并没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以,socket的出现只是可以更方便的使用TCP/IP协议栈而已,其对TCP/IP进行了抽象,形成了几个最基本的函数接口。比如create,listen,accept,connect,read和write等等。现在我们明白,如果一个程序创建了

网络的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位桌面平台标准,是...

文水县17035834817: java socket编程 怎样向指定网上的服务器请求建立连接,并接收数据包 -
仍苗双歧: 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通信.

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网