300分倾家荡产只为SOCKET!欢迎进入点击参与有分!(300分)

  • 主题发起人 主题发起人 攸游
  • 开始时间 开始时间

攸游

Unregistered / Unconfirmed
GUEST, unregistred user!
我用API做SOCKET广域网传输出现下列问题:
1、两台机子同时拨号上网,一台做服务器,一台做客户端,用SOCKET API做可就是
连接不上服务器 ;
2、对于 SOCKADDR_IN 中如:SIN_FAMILY,SIN_PORT, SIN_ADDR 不太清楚具体意义!
当然有很多问题有问各位大侠所以在线给分期望您的参与!!!
 
1、那证明你做错了
2、SIN_PORT:socket连接端口,SIN_ADDR:连接对端的ip地址
 
TO :CHENXZ
是: 我想问的一个是在BIND()前应设置哪些参数半相关三元组就可以标识一个进程
对吗,是不是还得用相关来做,要不就在广域网中找不到对方!
 
给你一段例程,用的是Internet域,流套接字,这程序是从UNIX移植到Windows下来的,充分
考虑到了移植性。

int SockCliConn(char *serv_addr,u_short serv_port)
/* 如果成功,返回Socket连接描述符;如果失败,返回值为:
-1:Socket创建错误
-2:连接错误
*/
{
int server_sock, /* 服务器套接字描述符 */
len;
static struct sockaddr_in serv_adr; /* 服务器端地址(Internet类型) */

/* ---------------------------------------------------------------
以下为初始化Socket动态链接库 */
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 2, 0 );
//设定为使用Winsock 2.0版
err = WSAStartup( wVersionRequested, &wsaData );
if (err!=0){
// 找不到可用的WinSock DLL.
return -1;
}

/* Confirm that the WinSock DLL supports 2.0.*/
/* Note that if the DLL supports versions greater */
/* than 2.0 in addition to 2.0, it will still return */
/* 2.0 in wVersion since that is the version we */
/* requested. */

if (LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!= 0){
// 找不到可以用的WinSock 2.0 DLL.
WSACleanup();
return -1;
}
/* --------------------------------------------------------------
以上为初始化Socket动态链接库,在UNIX下不需要 */


memset(&serv_adr, 0, sizeof(serv_adr)); /* 清除结构 */
serv_adr.sin_family = AF_INET; /* 设置地址类型 */
serv_adr.sin_addr.s_addr = inet_addr(serv_addr); /* 地址 */
serv_adr.sin_port = htons(serv_port);

if ((server_sock = socket(AF_INET, SOCK_STREAM, 0))<0){ /* 创建Socket */
//Form1->Memo1->Lines->Add("generate error");
return -1;
}
if (connect(server_sock, (struct sockaddr *)&serv_adr,
sizeof(serv_adr))<0){ /* 连接 */
//Form1->Memo1->Lines->Add("connect error");
closesocket(server_sock); //连接失败时关闭Socket描述符
return -2;
}
return server_sock;
}

不明白你的意思,bind()是服务器端程序用的,它怎么要找别的进程?它是要被别的进程找。
 
只有server才需要bind(),bind需要三个参数:socket套接字,端口和允许地址(一般设
sin_addr.s_addr = INADDR_ANY)
 
SIN_FAMILY 是指协议
SIN_PORT 是指端口,不一定是服务器端口,也可以是本地端口,就看你怎么用了
SIN_ADDR是是IP地址,可以是本地地址,也可是服务器地址,
我举个例子,
SENDTO这个函数,他需要两个TSockAddr
第一个是指本地的套接字,第二个是指服务器端的,
这是我的代码
Hostaddr.sin_family := AF_INET; //本地地址设定


// addr.sin_addr.S_addr := inet_addr(PChar(getBroadCastIp(GetLocalIP)));//??
hostaddr.sin_port := htons(6001);
bind(Skt1, Hostaddr, SizeOf(Hostaddr)); //执行绑定

{客户端地址设定}
ClientAddr.sin_family := AF_INET;
ClientAddr.sin_port := htons(ReceivePort);
ClientAddr.sin_addr.S_addr := inet_addr(pchar(getBroadCastIp(GetLocalIp)));

sendto(Skt1,CommOne,Sizeof(CommOne^),0,ClientAddr,sizeof(ClientAddr));
 
Sachow写的太简单了一点,连一些连接超时等都没有处理,还有错误的类型等
 
对不起各位,刚才说急了,
我写了服务端和客户端程序如下,可就是连接不上:
---------------
ClientSocket:=Socket(PF_INET,SOCK_STREAM,IPPROTO_IP);
IF ClientSocket=INVALID_SOCKET then
BEGIN
PShowMsg('1.创建socket错误!(');
result:=false;
exit;
END
ELSE
BEGIN
PShowMsg('1.创建socket成功!');
result:=true;
END;

// 设置参数
ca.sin_family:=PF_INET;
temp_port:=PPort;
ca.sin_port:=htons(StrToInt(trim(temp_port)));
temp_address:=PAddress;
hostaddr:=inet_addr(PChar(Trim(temp_address)));

if hostaddr=-1 then
begin
PShowMsg('主机ip地址错误!');
closesocket(ClientSocket);
exit;
end;
ca.sin_addr.S_addr:=hostaddr;
//连接服务器
if connect(ClientSocket,ca,sizeof(ca))<>0 then
begin
PShowMsg('2.连接到服务器错误!');
sleep(5);
closesocket(ClientSocket);
result:=false;
exit;
end
else
begin
result:=true;
PShowMsg('Clear');
PShowMsg('2.成功连接到服务器!');
Len := SizeOf(NewOpenType);
NewOpenType:=500000;
服务器端:
Port_1:=1024;
PShowMsg('1.系统开始创建Socket,请稍候......');

ServerSocket:=Socket(PF_INET,SOCK_STREAM,IPPROTO_IP);
if ServerSocket=INVALID_SOCKET then
begin
PShowMsg('2.系统创建接收Socket错误!');
result:=-1;
exit;
end
else
self.PShowMsg('2.系统创建Socket成功!');

ARGINT:=1;
ioctlsocket(ServerSocket,FIONBIO,ARGINT);

//进行监听参数设置
ca.sin_family:=PF_INET;
ca.sin_port:=htons(self.Port_1);
ca.sin_addr.S_addr:=INADDR_ANY;

if bind(ServerSocket,ca,sizeof(ca))=SOCKET_ERROR then
begin
PShowMsg('3.系统绑定错误,请更改接收端口!');
closesocket(ServerSocket);
result:=-1;
exit;
end
else
PShowMsg('3.系统绑定设置成功');

RASocket:=-1;
PShowMsg('4.系统开始进行监听客户端请求......');

 
ca.sin_family:=PF_INET;???
ca.sin_family:=AF_INET;
 
建议你先看看有关tcp/ip编程方面的书,你好象还不了解,这样写出来的东东肯定会出问题的
 
这又一个标准的对话模型, 你可以对昭一下程序, 估计是你的程序问题
连接成功要求几个条件 网络畅通 两端通讯地址对应 协议端口相同

以下引用的程序与实际程序略有出入, 下同)
sockfd = socket( AF_INET,SOCK_STREAM, 0);

// 首先建立一个 socket, 族为 AF_INET, 类型为 SOCK_STREAM.
// AF_INET = ARPA Internet protocols 即使用 TCP/IP 协议族
// SOCK_STREAM 类型提供了顺序的, 可靠的, 基于字节流的全双工连接.
// 由于该协议族中只有一个协议, 因此第三个参数为 0

bind( sockfd, ( struct sockaddr *)&serv_addr, sizeof( serv_addr));

// 再将这个 socket 与某个地址进行绑定.
// serv_addr 包括 sin_family = AF_INET 协议族同 socket
// sin_addr.s_addr = htonl( INADDR_ANY) server 所接受的所有其他
// 地址请求建立的连接.
// sin_port = htons( SERV_TCP_PORT) server 所监听的端口
// 在本程序中, server 的 IP和监听的端口都存放在 config 文件中.

listen( sockfd, MAX_CLIENT);

// 地址绑定之后, server 进入监听状态.
// MAX_CLIENT 是可以同时建立连接的 client 总数.
server 进入 listen 状态后, 等待 client 建立连接. 此时如果有

client 进行连接时, 也要先进行网络部分的初始化工作:
sockfd = socket( AF_INET,SOCK_STREAM,0));

// 同样的, client 也先建立一个 socket, 其参数与 server 相同.

connect( sockfd, ( struct sockaddr *)&serv_addr, sizeof( serv_addr));

// client 使用 connect 建立一个连接.
// serv_addr 中的变量分别设置为:
// sin_family = AF_INET 协议族同 socket
// sin_addr.s_addr = inet_addr( SERV_HOST_ADDR) 地址为 server
// 所在的计算机的地址.
// sin_port = htons( SERV_TCP_PORT) 端口为 server 监听的端口.

当 client 建立新连接时, server 使用 accept 来接受该连接:

accept( sockfd, (struct sockaddr*)&cli_addr, &cli_len);

// 在函数返回时, cli_addr 中保留的是该连接对方的信息
// 包括对方的 IP 地址和对方使用的端口.
// accept 返回一个新的文件描述符.


///////////////////////////////////
// 服务器程序:(省略了错误检查) //
///////////////////////////////////
#include <stdio.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>

#define PORT 8000
#define MAXLOG 10

main(){
int sock,newsock;
struct sockaddr_in myaddr;
char *buf="hello!/n";

sock=socket(AF_INET,SOCK_STREAM,0);

myaddr.sin_family=AF_INET;
myaddr.sin_port=htons(PORT);
myaddr.sin_addr.s_addr=inet_addr("195.95.95.1");
bzero(&myaddr.sin_zero,8);

bind(sock,&my_addr,sizeof(struct sockaddr));

listen(sock,MAXLOG);

while(1){
newsock=accept(sock,NULL,NULL);

if(!fork()){
write(newsock,buf,strlen(buf));
close(newsock);
}

while(waitpid(-1,NULL,WNOHANG)>0);
}
}
///////////////////////////////////
// 客户端程序:(省略了错误检查) //
///////////////////////////////////
#include <stdio.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>

#define PORT 8000


main(){
int sock;
struct sockaddr_in theiraddr;
char buf[256];
int n;

sock=socket(AF_INET,SOCK_STREAM,0);

theiraddr.sin_family=AF_INET;
theiraddr.sin_port=htons(PORT);
theiraddr.sin_addr.s_addr=inet_addr("195.95.95.1");
bzero(&their.sin_zero,8);

connect(sock,&their_addr,sizeof(struct sockaddr));

n=read(sock,buf,256):

if(n<0){
printf("read error!/n");
exit(0);
}

buf[n]='/0';

printf("%s",buf);
close(sock);
}

经编译后,在一个终端执行server,再开一个终端执行client,可以看到,在client终端上,会显示"hello!".




 
ca.sin_family:=PF_INET;???
ca.sin_family:=AF_INET;---代表什么?
我查过,值都等于2
我真的不太懂,可有什么办法难道说没有速成的吧!
不是有各位大侠在吗?
继续听各侠指示!

 
// AF_INET = ARPA Internet protocols 即使用 TCP/IP 协议族
在Windows Sockets 1中仅有一个地址族(AF_INET),它包含了数量不多的一些众所周知的
套接口类型和协议标识符。这在Windows Sockets 2中已经有所改变。除了现有的地址族,
套接口类型和协议标识符为了兼容性原因被保留以外,Windows Sockets 2加入了许多唯一
的但是可能并不为大家所知的地址族,套接口类型和协议标识符。 socket()函数用于根据
指定的地址族、数据类型和协议来分配一个套接口的描述字及其所用的资源。
如果协议protocol未指定(等于0),则使用缺省的连接方式。
 
TO:ramble:
我的上面那段代码不知你看了没有,
我把服务器和客户端同一台机子,就可以找到对方,
可两台同时拨号,不能找到对方我认为是不是虽然有一个IP如果不在
一个域中同样不能找到对方(按上述那样做)有没有办法,是不是
上面那段代码有错!!!
 
sockaddr_in = record
case Integer of
0: (sin_family: u_short;
sin_port: u_short;
sin_addr: TInAddr;
sin_zero: array[0..7] of Char);
sa_family: u_short;
sa_data: array[0..13] of Char) end;
WSAData=recordwVersion: Word;
wHighVersion: Word;
szDescription: array[0..WSADESCRIPTION_LEN] of Char;
szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char;
iMaxSockets: Word;
iMaxUdpDg: Word;
lpVendorInfo: PChar;);
end;
我要指定哪些值才能找到服务器请教各位??
 
好像你的serversocket没有listen
很简单,你可以参看delphi 的serversocket和clientsocket是如何监听和连接的。delphi已经
把这些粗重功夫封装起来了,你可以直接使用serversocket.active := true来监听,对于client
socket你只要设好serveraddress和port然后clientsocket.active := true连接。
 
sin_family: u_short;
sin_port: u_short;
sin_addr: TInAddr;
sin_zero: array[0..7] of Char); //设为0
sa_family: u_short;
 
TO:zhjwjan:
我省了。。LISTEN()没写上去,
TO:各位
能不能回答上个指定问题??
 
你可以先测试你的server是否已经写好了,
在dos下:telnet srv_ip port,如:telnet 22.1.3.4 8000
如果能够和server连上,则说明server端是好的,这时可以输入一些字符,按回车发送给
server。
 
To:chenxz:
非常感谢,我把服务器运行后 ,运行:telnet 202.11.13.14 1024 后
连接上了服务器按任意字符都可收到!
 
后退
顶部