S-JIS[2006-03-04/2007-04-16] 変更履歴

プログラミング言語比較

ソケット通信

 
ヘッダー #include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <winsock2.h>
#pragma comment(lib, "WS2_32.LIB")
#include <afxsock.h> import java.net.*; using System.Net.Sockets
初期化 なし WORD ver=MAKEWORD(2,2);
WSADATA wsa;
if(WSAStartup(ver,&wsa) != 0) fprintf(stderr,"WSAStartup error\n");
AfxSocketInit(); なし  
終了 なし WSACleanup(); なし なし  
TCPサーバー int ssoc=socket(AF_INET,SOCK_STREAM,0);
if(ssoc<0) perror("socket error");
SOCKET ssoc=socket(AF_INET,SOCK_STREAM,0);
if(ssoc==INVALID_SOCKET) fprintf(stderr,"socket error:%d\n",WSAGetLastError());
CAsyncSocketを継承したクラス(例:CServerSocket)を作る。
CServerSocket ssoc;
ssoc.Create(ポート, SOCK_STREAM);
ServerSocket ssoc = new ServerSocket(ポート,バックログ数); Socket ssoc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
struct sockaddr_in addr={ AF_INET };
addr.sin_port = htons(ポート);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(ssoc,(struct sockaddr*)addr,sizeof(addr))<0) perror("bind error");
struct sockaddr_in addr={ AF_INET };
addr.sin_port = htons(ポート);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(ssoc,(struct sockaddr*)addr,sizeof(addr))==SOCKET_ERROR) fprintf(stderr,"bind error:%d\n",WSAGetLastError());
EndPoint point = new IPEndPoint(IPAddress.Any, ポート);
ssoc.Bind(point);
if(listen(ssoc,バックログ数)<0) perror("listen error"); if(listen(ssoc,バックログ数)==SOCKET_ERROR) fprintf(stderr,"listen error:%d\n",WSAGetLastError()); if(!ssoc.Listen(バックログ数)) TRACE("Listen error:%d\n", ssoc.GetLastError()); ssoc.Listen(バックログ数);
オプション int val=1;
if(setsockopt(ssoc, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))<0) perror("setsockopt error");
int val=1;
if(setsockopt(ssoc, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))==SOCKET_ERROR) fprintf(stderr,"setsockopt error:%d\n",WSAGetLastError());
BOOL val=TRUE;
if(!ssoc.SetSockOpt(SO_REUSEADDR, &val, sizeof(val), SOL_SOCKET)) TRACE("SetSockOpt error:%d\n", ssoc.GetLastError());
ssoc.setReuseAddress(true); soc.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
受付タイムアウト fd_set mask;FD_ZERO(&mask);FD_SET(ssoc,&mask);
struct timeval tv={ タイムアウト時間[秒],[μ秒] };
int rc=select(ssoc+1,&mask,NULL,NULL,&tv);
if(rc<0) perror("accept-select error");
if(rc==0){ タイムアウト処理 }
fd_set mask;FD_ZERO(&mask);FD_SET(ssoc,&mask);
struct timeval tv={ タイムアウト時間[秒],[μ秒] };
int rc=select((int)ssoc+1, &mask, NULL, NULL, &tv);
if(rc==SOCKET_ERROR) fprintf(stderr,"accept-select error:%d\n",WSAGetLastError());
if(rc==0){ タイムアウト処理 }
  ssoc.setSoTimeout(タイムアウト時間);
accept()でタイムアウトするとSocketTimeoutExceptionが発生する
 
受付 for(;;){
 int soc=accept(ssoc, NULL, NULL);
 if(soc<0) perror("accept error");
 //通信処理
}
for(;;){
 int soc=accept(ssoc, NULL, NULL);
 if(soc==INVALID_SOCKET) fprintf(stderr,"accept error:%d\n",WSAGetLastError());
 //通信処理
}
CServerSocketでOnAccept()をオーバーライドしておく。通信が受け付けられるとOnAccept()が呼ばれるので、複数の通信を処理する為のループは必要ない。
void CServerSocket::OnAccept(int nErrorCode)
{
 CSocket soc; //接続ソケット
 if(!Accept(soc)){
  TRACE("Accept error:%d\n", this->GetLastError());
  return;
 }
 CSocketFile file(&soc, FALSE);
 //通信処理
}
for(;;) {
 Socket soc = ssoc.accept();
 //通信処理
}
while(true) {
 Socket soc = ssoc.Accept();
 //通信処理
}
TCPクライアント
接続
int soc=socket(AF_INET, SOCK_STREAM, 0);
if(soc<0) perror("socket error");

//ノンブロックに変更
int flag=fcntl(soc, F_GETFL, 0);
if(flag<0) perror("fcntl(GET) error");
if(fcntl(soc, F_SETFL, flag|O_NONBLOCK)<0) perror("fcntl(NONBLOCK) error");

struct sockaddr_in addr={AF_INET};
addr.sin_addr.s_addr=inet_aton("IPアドレス");
addr.sin_port=htons(ポート);
if(connect(soc, (struct sockaddr*)&addr, sizeof(addr))<0){
 if(errno!=EINPROGRESS) perror("connect error");
 //EINPROGRESS:コネクション要求は始まったが、まだ完了していない

 fd_set rmask,wmask;FD_ZERO(&rmask);FD_SET(soc,&rmask);wmask=rmask;
 struct timeval tv={ タイムアウト時間[秒],[μ秒] };
 int rc=select(soc+1, &rmask, &wmask, NULL, &tv);
 if(rc<0) perror("connect-select error");
 if(rc==0){ タイムアウト処理 }
 if(rc==2){ //読み書きが同時に出来る場合
#if Solaris
  int val;
  socklen_t len=sizeof(val);
  if(getsockopt(soc,SOL_SOCKET,SO_ERROR, &val,&len)>=0) {
#elif Linux
  struct sockaddr_in name;
  socklen_t len=sizeof(name);
  if(getpeername(soc,(struct sockaddr*)&name,&len)>=0) {
#endif
   // 既にデータが来ている
  }else{
   // コネクト失敗
  }
 }
}
//フラグを元に戻す
if(fcntl(soc, F_SETFL, flag)<0) perror("fcntl(END) error");
SOCKET soc=socket(AF_INET, SOCK_STREAM, 0);
if(soc==INVALID_SOCKET) fprintf(stderr,"socket error:%d\n",WSAGetLastError());

//ノンブロックに変更
u_long flag=1;
if(ioctlsocket(soc, FIONBIO, &flag)==SOCKET_ERROR) fprintf(stderr,"ioctl(NONBLOCK) error:%d",WSAGetLastError());

struct sockaddr_in addr={AF_INET};
addr.sin_addr.s_addr=inet_addr("IPアドレス");
addr.sin_port=htons(ポート);
if(connect(soc, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR){
 int errno=WSAGetLastError();
 if(errno!=WSAEWOULDBLOCK) fprintf(stderr,"connect error:%d\n",errno);

 fd_set rmask,wmask;FD_ZERO(&rmask);FD_SET(soc,&rmask);wmask=rmask;
 struct timeval tv={ タイムアウト時間[秒],[μ秒] };
 int rc=select((int)soc+1, &rmask, &wmask, NULL, &tv);
 if(rc==SOCKET_ERROR) fprintf(stderr,"connect-select error:%d\n",WSAGetLastError());
 if(rc==0){ タイムアウト処理 }
 if(rc==2){ //読み書きが同時に出来る場合
  int val;
  int len=sizeof(val);
  if(getsockopt(soc,SOL_SOCKET,SO_ERROR,(char*)&val,&len)!=0) {
   // 既にデータが来ている
  }else{
   // コネクト失敗
  }
 }
}

//ブロックモードにする
flag=0;
if(ioctlsocket(soc, FIONBIO, &flag)==SOCKET_ERROR) fprintf(stderr,"ioctl(BLOCK) error:%d",WSAGetLastError());
CSocket soc;
if(!soc.Create(0, SOCK_STREAM)) TRACE("Create error:%d\n",  soc.GetLastError());

if(!soc.Connect("IPアドレス",ポート)) TRACE("Connect error:%d\n",  soc.GetLastError());

CSocketFile file(&soc, FALSE);
SocketAddress addr = new InetSocketAddress("IPアドレス",ポート);
Socket soc = new Socket();
soc.connect(addr, タイムアウト時間);
IPAddress addr = IPAddress.Parse("IPアドレス");
EndPoint point = new IPEndPoint(addr, ポート);
Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
soc.Connect(point);
ホスト名 struct hostent *ent=gethostbyname("ホスト"); struct hostent *ent=gethostbyname("ホスト"); soc.Connect("ホスト",ポート) SocketAddress addr = new InetSocketAddress("ホスト",ポート); IPAddress addr = Dns.Resolve("ホスト").AddressList[0];
待ち fd_set mask;FD_ZERO(&mask);FD_SET(soc,&mask);
struct timeval tv={ タイムアウト時間[秒],[μ秒] };
int rc=select(soc+1, &mask, NULL, NULL, &tv); //受信の場合
int rc=select(soc+1, NULL, &mask, NULL, &tv); //送信の場合
if(rc<0) perror("select error");
if(rc==0){ タイムアウト処理 }
fd_set mask;FD_ZERO(&mask);FD_SET(soc,&mask);
struct timeval tv={ タイムアウト時間[秒],[μ秒] };
int rc=select((int)soc+1, &mask, NULL, NULL, &tv); //受信の場合
int rc=select((int)soc+1, NULL, &mask, NULL, &tv); //送信の場合
if(rc==SOCKET_ERROR) fprintf(stderr,"select error:%d\n",WSAGetLastError());
if(rc==0){ タイムアウト処理 }
  soc.setSoTimeout(タイムアウト時間);
read()でタイムアウトするとSocketTimeoutExceptionが発生する
soc.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout , タイムアウト時間); //受信の場合
soc.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, タイムアウト時間); //送信の場合
//受信の場合
if(!soc.Poll(タイムアウト時間, SelectMode.SelectRead))
{
 タイムアウト処理
}
//送信の場合
if(!soc.Poll(タイムアウト時間, SelectMode.SelectWrite))
{
 タイムアウト処理
}
送信 int slen=send(soc,バッファ,送信サイズ,0);
if(slen<0) perror("send error");
int slen=send(soc,バッファ,送信サイズ,0);
if(slen==SOCKET_ERROR) fprintf(stderr,"send error:%d\n",WSAGetLastError());
file.Write(バッファ,送信サイズ); OutputStream os = soc.getOutputStream();
os.write(バッファ,0,送信サイズ);
int slen = soc.Send(バッファ,送信サイズ, SocketFlags.NONE);
受信 int rlen=recv(soc,バッファ,バッファサイズ,0);
if(rlen<0) perror("recv error");
int rlen=recv(soc,バッファ,バッファサイズ,0);
if(rlen==SOCKET_ERROR) fprintf(stderr,"recv error:%d\n",WSAGetLastError());
UINT rlen=file.Read(バッファ,バッファサイズ); InputStream is = soc.getInputStream();
int rlen = is.read(バッファ);
int rlen = soc.Receive(バッファ);
情報取得 struct sockaddr_in addr={0};
int len=sizeof(addr);
if(getsockname(soc, &addr, &len)<0) perror("getsockname error");
char *name=inet_ntoa(addr.sin_addr);
int port=ntohs(addr.sin_port);
struct sockaddr_in addr={0};
int len=sizeof(addr);
if(getsockname(soc, &addr, &len)==SOCKET_ERROR) fprintf(stderr,"getsockname error:%d\n",WSAGetLastError());
char *name=inet_ntoa(addr.sin_addr);
int port=ntohs(addr.sin_port);
CString name;
UINT port;
soc.GetPeerName(name, port);
InetAddress addr = soc. getInetAddress();
String name = addr.getHostAddress();
int port = soc.getPort();
IPEndPoint (IPEndPoint)point = soc.RemoteEndPoint();
string name = point.Address.ToString();
int port = point.Port;
切断 shutdown(soc,種類);
SHUT_RD, SHUT_WR, SHUT_RDWR
shutdown(soc,種類);
SD_RECEIVE, SD_SEND, SD_BOTH
soc.ShutDown(種類);
receives, sends, both
soc.shutdownInput();
soc.shutdownOutput();
soc.Shutdown(種類);
SocketShutdown.Receive, Send, Both
クローズ close(soc);
close(ssoc);
closesocket(soc);
closesocket(ssoc);
file.Close();soc.Close();
ssoc.Close();
os.close();is.close();soc.close();
ssoc.close();
soc.Close();
ssoc.Close();

言語比較全般へ戻る / 参考文献 / プログラム記号比較 / 技術メモへ戻る
メールの送信先:ひしだま