WinSock 네트워크 프로그래밍 기본(2) 클라이언트
8169 단어 네트워크 프로그래밍
TCP는 두 컴퓨터 간의 신뢰할 수 있는 데이터 전송을 제공할 수 있으며 응용 프로그램이 TCP 통신을 사용할 때 두 컴퓨터 사이에 가상 연결을 구축하고 연결된 후에 컴퓨터 간에 양방향 바이트 흐름으로 데이터 교환을 할 수 있다.
다음은 간단하게 데이터를 보내는 클라이언트의 실현입니다.
클라이언트의 연결을 쉽게 만들 수 있습니다.
1. 플러그인을 만들고 addrinfo 대상을 정의하고 이 값을 초기화합니다 (이 대상은 sockaddr 구조를 포함합니다)
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC; // IPv4 IPv6
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
getaddrinfo 함수를 호출하여 서버 IP 주소 (명령행 매개 변수로 전달) 와 포트를 확인합니다.
#define DEFAULT_PORT "27015"
// Resolve the server address and port
iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed: %d
", iResult);
WSACleanup();
return 1;
}
socket 프로토타입:
socket(
IN int af,//프로토콜의 주소족, IPv4를 사용하여 Winsock을 설명하고 AF 로 설정INET
IN int type,//소켓 유형, TCP/IP SOCKSTREAM, UDP/IP를 SOCK 로 설정DGRAM
IN int protocol//지정된 주소 패밀리 및 유형에 다중 포털이 있는 전송 제한을 위해 TCP를 IPPROTO 로 설정TCP, UDP를 IPPROTO 로 설정UDP
);
socket을 호출하여 플러그인 생성, 오류 검출
SOCKET ConnectSocket = INVALID_SOCKET;
ptr=result;
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld
", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
2. 접속된 서버 이름입니다.(TCP/IP에서 수신 서버의 IP 주소와 포트 번호)
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
//
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!
");
WSACleanup();
return 1;
}
클라이언트 프로그램은 플러그인을 만든 후에 연결 함수를 사용하여 서버와 연결을 요청합니다. 연결 원형은 다음과 같습니다.
int WSAAPI connect(
IN SOCKET s,//연결할 socket
IN construct sockaddr FAR * name,//연결 정보를 저장할 주소 구조를 나타냅니다.
IN int namelen//매개변수 2는 주소 구조의 크기를 가리킵니다.
);
3. 데이터를 보내고 받는다.
데이터를 수발하는 것이야말로 네트워크 프로그래밍의 주제이다. 이미 연결된 플러그인에 데이터가 발생하면send나 WSASend(WinSock2에서)를 사용할 수 있고recv와 WSARecv를 사용할 수 있다.송수신 데이터는char 형식을 사용합니다.
#define DEFAULT_BUFLEN 512
int recvbuflen = DEFAULT_BUFLEN;
char *sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
iResult = send(ConnectSocket, sendbuf, (int) strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed: %d
", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld
", iResult);
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d
", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iResult > 0)
printf("Bytes received: %d
", iResult);
else if (iResult == 0)
printf("Connection closed
");
else
printf("recv failed: %d
", WSAGetLastError());
} while (iResult > 0);
송수신 데이터가 반환되는 모든 오류 코드는 SOCKETERROR, 오류가 발생하면 WSAGetLastError () 를 호출하여 자세한 오류 정보를 가져옵니다.
자주 발생하는 오류:
WSAECONNABORTED와 WSAECONNRESET: 연결이 닫히고 있습니다(시간 초과 또는 통신 방송으로 연결이 닫히고 있음). WSAEWOULDBLOCK: 소켓이 비막힘 모드 또는 비동기 상태입니다.
send와recv 함수 원형을 사용합니다.
int send(
SOCKET s,//소켓 핸들
const char FAR* buf,//보낼 데이터의 버퍼 주소
int len,//버퍼 길이
int flags//에서 지정한 호출 방식입니다. 일반적으로 0으로 설정됩니다.
);
int recv(
SOCKET s,
char FAR* buf,
int len,
int flags
);
send 함수는 연결된 바이트에 버퍼 내의 데이터를 보내고, 데이터를 보내는 실제 바이트 수를 되돌려주며,recv 함수는 상대방으로부터 데이터를 받아서 지정한 버퍼에 저장합니다.flag 매개 변수는 일반적으로 두 함수에서 0으로 설정됩니다.
막힘 모드에서send는 모든 데이터가 전송될 때까지 (또는 오류가 발생할 때까지) 라인의 실행을 막고,recv 함수는 버퍼가 지정한 크기까지 가능한 한 많은 현재 정보를 되돌려줍니다.
함수 실행 실패가 INVALID 로 반환됨SOCKET (-1), closesocket 함수를 호출해서 닫아야 합니다.오류가 발생하지 않으면 함수가 0을 반환하고 그렇지 않으면 SOCKET 를 반환합니다.ERROR.함수는 다음과 같이 사용됩니다.
int closesocket(
__in SOCKET s//함수의 유일한 매개 변수는 닫을 소켓의 핸들입니다
);
4. 연결을 끊고 플러그인을 닫는다. (클라이언트가 데이터를 보냈을 때 shutdown 함수와SD SEND 매크로를 사용하여 플러그인을 보낼 수 있고 클라이언트는 서버 플러그인에서 데이터를 받아들일 수 있다)
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d
", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
closesocket(ConnectSocket);
WSACleanup();
전체 클라이언트 코드 포함:
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <IPHlpApi.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Mswsock.lib")
#pragma comment(lib, "Advapi32.lib")
#define DEFAULT_PORT "27015"
#define DeFAULT_BUFLEN 512
int main(int argc, char* argv[])
{
WSADATA wsaData;
int iResult;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char *sendbuf = "this is a test";
char recvbuf[DeFAULT_BUFLEN];
int recvbuflen = DeFAULT_BUFLEN;
SOCKET ConnectSocket = INVALID_SOCKET;
if (argc != 2)
{
printf("usage: %s server-name
", argv[0]);
}
// winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed: %d
", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
//
iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed: %d
", iResult);
WSACleanup();
return 1;
}
// ,
for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
{
//
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET)
{
printf("Error at socket(): %ld
", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
//
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
//
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET)
{
printf("Unable to connect to server!
");
WSACleanup();
return 1;
}
// sendbuf
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf) + 1, 0);
if (iResult == SOCKET_ERROR)
{
printf("send failed:%d
", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Byte Send:%ld
", iResult);
//
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
printf("shutdown faild: %d
", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
//
do
{
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iResult > 0)
printf("Byte received: %d
", iResult);
else if (iResult == 0)
printf("connection closed
");
else
printf("recv failed: %d
", WSACleanup());
} while (iResult > 0);
//
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
본문 링크:http://www.bugcoding.com/entry/10
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Java 네트워크 프로그래밍의 간단한 서버 클라이언트 응용 사례본고는 자바 네트워크 프로그래밍의 간단한 서버 클라이언트 응용을 실례로 다루고 있다.여러분에게 참고할 수 있도록 나누어 드리겠습니다.구체적으로 다음과 같습니다. 우리는 소켓 클래스의 구조 함수를 사용하여 소켓을 열 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.